RNA Seq Pre-Processing

Peripheral Blood CD8+ T cell in Pre-Anti-PD-1 Antibody vs Post-Anti-PD-1 Antibody Treated Melanoma Patients

By Dong Hoon Han BCB420 2020
*References are at the bottom of the html!

Introductory Questions

Why is the dataset of interest to you?

I am interested in immunology, especially in T cells, which are driving the next generation immunotherapy treatments for cancer.

Immunocheckpoint inhibitors such as CTLA-4 and PD-1 inhibitors have been particularly successful, which inhibit the break of activated T cells. Unfortunately, although they have been successful, they did not achieve the same degree of success in every patients.

The dataset from this study would allow me to probe into the transcriptomes of those break-inhibited activated CD8+ cytotoxic T cells vs normal activated CD8+ cytotoxic T cells. This would help me to hypothesize the different mechanisms of why those break-inhibited CD8+ Ts are more effective against cancer vs normal activated CD8+ Ts, and possibly why this therapy may not be responding against certain patients.

Unfortunately, this dataset does not indicate whether the patient has survived or succumbed to the cancer, most likely due to privacy issues.

Control and Test conditions of the dataset?

Patients with stage IV melanoma were enrolled for treatment with pembrolizumab (pembro), anti-PD-1 antibody (2 mg kg^-1 by infusion every 3 weeks). After receiving their consents, peripheral blood was obtained before treatment and before each pembro infusion every weeks for 12 weeks. (Huang et al. 2017)

For RNA sequencing experiments, total CD8 T cells were sorted using a dump/dead-CD3+ CD8+ gating strategy, by BD Aria Sorter (Huang et al. 2017). Dump here means the exclusion channel which is used for staining everything you do not want.

So the controls are the RNA sequencing of total CD8 T cells before pembro infusion.

The tests are the RNA sequencing of total CD8 T cells 3 weeks after each pembro infusion.

Overall the samples are divided into cycle 1, 2, 3, 4, as pembro was injected at Week 0, 3, 6, 9, and the blood was drawn before pembro injection at Week 0, 3, 6, 9, 12.

Pretreatment samples are week 0 pre-treatment peripheral blood CD8 T cells. These are the controls.

Cycle 1 samples are week 3 peripheral blood CD8 T cells after the week 0 pembro injection.

Cycle 2 samples are week 6 peripheral blood CD8 T cells after the week 0, 3 pembro injection.

Cycle 3 samples are week 9 peripheral blood CD8 T cells after the week 0, 3, 6 pembro injection.

Cycle 4 samples are week 12 peripheral blood CD8 T cells after the week 0, 3, 6, 9 pembro injection.

Cycle 2 samples were not included in this analysis, because other samples all had 3 replicates (from 3 patients) whereas there was only one cycle 2 sample (from a single patient).

GSE Object

Loading Libraries

Loading in the GSE by using GEOquery package & Extracting Relevant Information

Overall.Design
Transcriptional profiles of CD8+ T cells from peripheral blood of melanoma patients before and after anti-PD1 therapy

Experiment.Summary
RNA-Seq analysis was used to study the profile of CD8 t cells from melanoma patients before and after treatment to understand if we can detect transcriptional changes in peripheral blood

GPL.Title Submission Last.Update Organism Number.of.Series Number.of.Samples
illumina NextSeq 500 (Homo sapiens) Mar 14 2017 Mar 14 2017 Homo sapiens 1 13

:::

Raw Counts Matrix

Loading in the Raw Counts Matrix

Two count matrixes: normalized & raw counts, using the raw counts matrix

trying URL 'https://ftp.ncbi.nlm.nih.gov/geo/series/GSE96nnn/GSE96578/suppl//GSE96578_AH_PBMC_RNAseq_normcounts.txt.gz?tool=geoquery'
Content type 'application/x-gzip' length 752117 bytes (734 KB)
==================================================
downloaded 734 KB

trying URL 'https://ftp.ncbi.nlm.nih.gov/geo/series/GSE96nnn/GSE96578/suppl//GSE96578_AH_PBMC_RNAseq_rawcounts.txt.gz?tool=geoquery'
Content type 'application/x-gzip' length 798930 bytes (780 KB)
==================================================
downloaded 780 KB

First 6 rows of Raw Counts Matrix


Dimension of the Raw Counts Matrix

[1] 28383    16


What each GSMs correspond to

X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13
GSM2536183 GSM2536184 GSM2536185 GSM2536186 GSM2536187 GSM2536188 GSM2536189 GSM2536190 GSM2536191 GSM2536192 GSM2536193 GSM2536194 GSM2536195
R_S416 R_S417 R_S418 R_S419 R_S420 R_S426 R_S427 R_S428 R_S429 R_S430 R_S431 R_S432 R_S433


Comprehensive Sample Information Matrix -> Not including R_S418 Cycle2 treatment in the downstream analysis, because there is no biological replicate for this Cycle2 treatment RNA-seq experiment

##################################################################################
# What do each of these R_S4xx mean? i.e. what do each of these samples represent? ----
##################################################################################

sample.info.matrix <- data.frame()

# i under GSE96578@gsms is a GSE object, which can be probed using Meta() function
# Use for loop to probe each of the 13 samples
for(i in GSE96578@gsms){
  sample.info.matrix <- rbind(sample.info.matrix,
                       data.frame(Meta(i)$title, Meta(i)$characteristics_ch1[3],Meta(i)$characteristics_ch1[1],
                                  Meta(i)$characteristics_ch1[5], Meta(i)$library_strategy, Meta(i)$instrument_model))
}
colnames(sample.info.matrix) <- c("Title","Treatment", "Patient Age", "Disease State",
                                  "Data Type", "Instrument")
# sample.info.matrix

# Decided not to include R_S418 Cycle2 treatment in the downstream analysis, because
# there is no replicate for this Cycle2 treatment RNA-seq experiment
sample.info.matrix <- sample.info.matrix[-3,]
cd8_exp <- dplyr::select(.data = cd8_exp, -R_S418)
# head(sample.info.matrix)
# head(cd8_exp)


# Let's create a more descriptive label for each of the samples

descriptive.label <- c("pt.A.PreTreat", "pt.A.Cycle1", "pt.A.Cycle3", "pt.A.Cycle4",
                       "pt.B.PreTreat", "pt.B.Cycle1", "pt.B.Cycle3", "pt.B.Cycle4",
                       "pt.C.PreTreat", "pt.C.Cycle1", "pt.C.Cycle3", "pt.C.Cycle4")

sample.info.matrix %>% mutate(Label = descriptive.label) -> sample.info.matrix

sample.info.matrix %>% 
  mutate(Patient = stringr::str_match(string = sample.info.matrix$Label,
                                      pattern = "(?<=\\.)(.*)(?=\\.)")[,1]) %>%
  mutate(Treatment = stringr::str_match(string = sample.info.matrix$Label,
                                        pattern = "(?<=pt\\.[A-z]\\.)(.*)")[,1]) -> sample.info.matrix

kable(sample.info.matrix)

Title Treatment Patient Age Disease State Data Type Instrument Label Patient
R_S416 PreTreat age: 81 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.A.PreTreat A
R_S417 Cycle1 age: 81 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.A.Cycle1 A
R_S419 Cycle3 age: 81 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.A.Cycle3 A
R_S420 Cycle4 age: 81 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.A.Cycle4 A
R_S426 PreTreat age: 71 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.B.PreTreat B
R_S427 Cycle1 age: 71 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.B.Cycle1 B
R_S428 Cycle3 age: 71 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.B.Cycle3 B
R_S429 Cycle4 age: 71 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.B.Cycle4 B
R_S430 PreTreat age: 67 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.C.PreTreat C
R_S431 Cycle1 age: 67 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.C.Cycle1 C
R_S432 Cycle3 age: 67 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.C.Cycle3 C
R_S433 Cycle4 age: 67 disease state: melanoma patient RNA-Seq Illumina NextSeq 500 pt.C.Cycle4 C

Contact Information and Data Processing & Extraction Protocol

Contact Information

contact_address contact_city contact_country contact_department contact_institute contact_name
421 Curie Blvd Philadelphia USA Microbiology & Immunology University of Pennsylvania E,JOHN,WHERRY

Data Processing Protocol for all Samples from Fastq to Raw Counts

[1] "The fastqs were aligned using STAR 2.5.2a and hg19"                                                             
[2] "The aligned files were processed using PORT gene-based normalization ( https://github.com/itmat/Normalization )"
[3] "The differential gene expression was done with limma"                                                           
[4] "Genome_build: hg19"                                                                                             
[5] "Supplementary_files_format_and_content: Raw counts and normalized counts"                                       

Extraction Protocol for all Samples

[1] "RNA was isolated using the Qiagen RNeasy micro kit (#74034) according to the manufacturer's protocol"                                                                   
[2] "RNA-seq libraries were prepared using the SMARTer Stranded Total RNA-Seq Kit for Pico Input Mammalian from Clonetech according to the manufacturer's protocol (#635007)"
[3] "The libraries were sequenced on an Illumina NextSeq machine using a 300 cycle high output flow cell (#15057929)"                                                        

Outliers, Replicates & Duplicates

Gene Duplicates

Duplicates were handled the following way.

Dimension of the Raw Count Matrix

[1] 28383    15

There are 28383 features (i.e. genes/nongenes) & 12 out of 15 columns are samples; other 3 are ID, gene coordinate, gene symbol.
This raw count matrix consists of 4 triplet replicates so 12 samples in total: Pre-treatment, Cycle 1, Cycle 3, Cycle 4

I’ve created the table of row counts for each of the “gene” name, using code learnt from the class. This is to probe the gene duplicates in my data.

Y_RNA U3 snoU13 Metazoa_SRP SNORA40 7SK U1 U6 SNORA31 SNORA70
174 19 9 8 7 6 4 4 3 3

Why do certain factors like Y_RNA appear more than once in the gene row? Let’s check it out using head() and logical subsetting to select those rows with “Y_RNA”.

Some factors like Y_RNA appears multiple times because there are different Y_RNA at different chromosomal regions. Y RNAs are small non-coding RNAs, SNOR are small nucleolar RNA, and Us are small nuclear RNA.

From the notes I’ve took during lecture and my opinion, there is no need to filter them out, since they are unique features of the cells that map to different chromosomal regions.

But we do need to filter out weakly expressed and noninformative (non-aligned) features, all of which can be done in edgeR.

Filtering out Outliers (How many were filtered out)

Genes with very low count across all libraries provide very little evidence for differential expression. Moreover, the discreteness of these low counts interferes with some of the statistical approximations used in edgeR package (M D Robinson, McCarthy, and Smyth 2010). Thus, these genes should be considered as outliers and need to be filtered out before downstream analysis.

A gene also should be filtered with count-per-million (CPM) rather than raw counts, as raw counts do not account for differences in library sizes between samples(M D Robinson, McCarthy, and Smyth 2010).

Before getting started, let’s figure out the definition of counts per million, or CPM.

\(CPM_{i} = \frac{X_{i}}{N}\cdot 10^{6}\)

Here \(X_{i}\) is the count for certain gene and \(\frac{N}{10^{6}}\) is the number of fragments you sequenced in the library per million. By processing the raw count to counts per million, the library size differences between samples can be accounted for.

Raw count matrix is turned into counts per million matrix, in order to filter out the genes that have abnormally low counts.

                     pt.A.PreTreat pt.A.Cycle1 pt.A.Cycle3 pt.A.Cycle4 pt.B.PreTreat pt.B.Cycle1
gene:ENSG00000000003      0.000000    0.000000    0.000000    1.464792      1.456811    2.869313
gene:ENSG00000000005      0.000000    0.000000    0.000000    0.000000      0.000000    0.000000
gene:ENSG00000000419     22.146292   30.199984    9.429144   23.436665     13.111296    8.607939
gene:ENSG00000000457      7.909390    6.039997   17.286764   11.718332     10.197675   14.346564
gene:ENSG00000000460      3.163756    0.000000    4.714572    2.929583      5.827243    4.303969
gene:ENSG00000000938     56.947608    6.039997   75.433151   35.154997     23.308971    8.607939


EdgeR recommends us to remove features without at least 1 read per million in n of the samples, where n is the size of the smallest group of replicates There are 3 samples of each cycle (i.e. pre-treatment, cycle1, cycle 3, cycle4) if I do not include Cycle2 treatment so n = 3

Using the above principle, the filtered gene matrix is generated, and the number of features between before and after the filtering is shown

Number of Features Number of Columns
Before 28383 15
After 17118 15

How many outliers were removed?
11256 genes that had very low counts, i.e, outliers, across the samples were filtered out.

[1] 11265     0


Interestingly, many duplicate genes were also filtered out during the process

Before

Y_RNA U3 snoU13 Metazoa_SRP SNORA40 7SK U1 U6 SNORA31 SNORA70
174 19 9 8 7 6 4 4 3 3

After

Y_RNA U3 SNORA40 7SK CRIP1 CRYBG3 GOLGA7B IDS KBTBD4 KIAA0391
29 4 3 2 2 2 2 2 2 2

Normalization


Normalization is a necessary step to adjust the data so that we can focus more on biological variation than technical variation.

Boxplot of the Filtered Matrix after CPM & log2 transformation (Pre-Normalization)

Density plot of the Filtered Matrix after CPM & log2 transformation


M vs A Plot of Cycle 1 vs Pre-Treatment CD8+ T RNA-seq

This plot is the basis of trimmed mean, which is the average after removing upper and lower percentage of the data points. And that percentages are 30% of the M values and 5% of the A values by default.

Forming DGEList and calcNormFactors() to find a set of scaling factors for the library sizes that minimize the log fold changes between the samples for most genes. The default method for computing these scale factors uses a trimmed mean of M- values (TMM) between each pair of samples (Mark D Robinson and Oshlack 2010)
The product of the library size and the scaling factor is called effective library size, which replaces the original library size in all downstream analysis.

# Trimmed Mean - is the average after removing the upper and lower percentage of the data points 
# 30% of the M values and 5% of the A values by default

# Application of TMM to the dataset 

# Creating an edgeR container for RNAseq count data
filtered_data_matrix <- as.matrix(cd8_exp_filtered[,4:15])
rownames(filtered_data_matrix) <- cd8_exp_filtered$id

# colnames(cd8_exp_filtered)[4:15]

# Creating DGElist object from the filtered expression matrix
# Here, group parameter is a vector/factor that gives the experimental group/condition for each sample/library
# For this dataset, it is the different cycles of Anti-PD-1 antibody treatment to the melanoma patients
TreatmentType <- sample.info.matrix$Treatment
names(TreatmentType) <- sample.info.matrix$Title
# TreatmentType
  
dGEList.for.TMM <-  DGEList(counts=filtered_data_matrix, group= TreatmentType)

# Removing TreatmentType, filtered_data_matrix

rm(TreatmentType, filtered_data_matrix)

# edgeRUsersGuide()
# The calcNormFactors function normalizes for RNA composition by finding a set of scaling
# factors for the library sizes that minimize the log-fold changes between the samples for most
# genes. The default method for computing these scale factors uses a trimmed mean of M-
#   values (TMM) between each pair of samples [30]

# Robinson, M.D. and Oshlack, A. (2010). A scaling normalization method for
# differential expression analysis of RNA-seq data. Genome Biology 11, R25.

# We call the product of the original library
# size and the scaling factor the effective library size. The effective library size replaces the
# original library size in all downsteam analyses.

dGEList.for.TMM <-  calcNormFactors(dGEList.for.TMM)
# str(dGEList.for.TMM)

Plot of the Normalized Data before & after TMM normalization

Side to Side Boxplot of Before & After TMM

There is a great difference before and after the normalization. The interquartile range (between Q1 and Q3) has narrowed down a lot. There are also more outliers in the highly expressed genes in all samples.

Side to Side Density Plot - Before (left) & After (right) Normalization

The two density plots also show great differences. The log2-cpm transformed gene counts in 5 range have decreased a lot compared to the original pre-normalization sample.

Plot of Mean - Variance after Normalization

This plot shows us how the different dispersion values we have calculated influence the data.
The raw variances of the counts are the gray dots
Variance = mean (assumption of poisson distribution) is the solid black line.
Variances estimated using the tagwise dispersions are blue dots.
Variances estimated using the common dispersions are the solid blue lines.

Binned Common Display Variance = Red X
Common Dispersion for each bin of genes and show the variances computed from those binned common dispersions and the mean expression level of the respective bin of genes.
Blue line shows the mean-variance relationship for a Negative Binomial model with common dispersion.

In a RNA seq experiment, we map the sequencing reads to the reference genome and count how many reads fall within a given gene (or exon).
In other words, the inputs for statistical analysis are discrete non-negative integers or counts for each gene in each sample.

The total number of reads for each sample tends to be in millions while the counts per gene vary considerably but tend to be in tens, hundreds, or thousands.

Therefore, the chance of a given read to be mapped to any specific gene is rather small.
Poisson process is when discrete events are sampled out of a large pool with low probability, and earlier iterations of RNA-seq analysis modeled sequencing data as a Poisson distribution.
One problem with Poisson distribution is that variability of read counts in sequencing experiments is greater than the variance Poisson distribution allows, which assumes its variance is equal to the mean.

The negative binomial (NB) distribution, which is used instead, can be described as Poisson-Gamma mixture distribution, which allows the extra variance by including the rate parameter gamma.

All of the above interpretation was taken from the following source, which helped me understand how statisticians modeled this reads to counts event (Lipp 2016)!

Handling Biological Replicates

Biological replicates are the same experiments performed on multiple samples that are of same type of cells/tissues.
This is different from technical replicates, which are same experiments performed on single sample multiple times.
For my dataset, the 4 groups of biological replicates are Pre-treatment, Cycle 1, Cycle 3, Cycle 4 samples. Each group has 3 biological replicates, from 3 different patients

We can visualize the clustering of the replicates by Multidimensional Scaling graph.

The same patient samples clustered closely together along x-axis. Within the same patient samples, there were variations of the samples along the y-axis, depending on the treatment. Interesting, while treatment cycle 1 samples were the outliers for patient A & B, treatment cycle 3 sample was the outlier for patient C.



Plot of Mean Variance

Same plot in the Normalization Tab

According to, edgeR, dispersion squared is biological coefficient of variation (BCV) so dispersion is a measure of how much variation there is in the samples. The raw variances of the counts are the gray dots

Variance = mean (assumption of poisson distribution) is the solid black line.
Variances estimated using the tagwise dispersions are blue dots.
Variances estimated using the common dispersions are the solid blue lines.

My samples seem to fit well with the NB distribution in terms of mean-variance.

I have decided to keep these biological replicates of Cycle 1, 3, 4, and Pre-treatment for my downstream analysis.

Expression Values

Identifer Mapping

The data just doesn’t contain the identifers that we’re interested in - i.e genes. Technology itself works on a different level and tracks different information so often aren’t working gene level data - like for RNA-seq, it deals with read counts of short fragments of RNA that don’t necessarily map to an individual gene.

In other words, the short fragments of RNA may not represent (i.e. map to) a gene.

The perks of RNA seq, though, is that it can be re-analyzed to give new information to uncover new things, as new genes & regulatory mechanisms are being discovered.

Connecting to hg19 (GRCh37) human gene ensembl in order to get the HGNC symbols & Using getBM() function to retrieve the attributes - Ensembl gene ids and HGNC symbols - that matches the Ensembl gene ids in my dataset.
hg19 because the reads were aligned using hg19 reference genome (stated in the data processing protocol section).

Probing my new retrieved mapping with head()

The difference between the number of mappings that are not missing values or empty strings and the number of rows in the normalized set - This doesn’t necessarily mean we are missing only that many

[1] 2707

Merging the normalized_counts matrix to the newly mapped idenfiers & head() to get the merged normalized_counts_annot matrix its first look

Expression values having different ensembl gene ids but map to same HUGO symbols OR not mapping to current HUGO symbols

To determine the expression values that have different ensembl gene ids but map to same HUGO symbols, I needed to check whether there were rows with same HUGO symbols but with different ensembl gene ids in the merged normalized_count_annot matrix.

To check for same HUGO symbols, I first checked the difference between the total length of the HUGO symbols vs length of the unique HUGO symbols

Total Length of HUGO Symbols in the merged dataset

[1] 17120

Length of Unique HUGO Symbols in the merged dataset

[1] 14411

Difference between the total length of the HUGO symbols vs length of the unique HUGO symbols
i.e. The number of duplicated HUGO symbols

[1] 2709

I then took a glance at the duplicated HUGO symbols data.frame with head().



Seems like most if not all duplicated HUGO symbols are either empty string or missing values!

What I’ve realized though is that when these unmapped ensembl gene ids are also mapped to “external_gene_name” attribute, they all got those names that were searchable on the https://grch37.ensembl.org website. And few of them were even searchable on the HUGO https://www.genenames.org/ website, while most of them were not searchable on HUGO website.

Unmapped Ensembl Gene Ids mapped to External Gene Name attribute



Let’s check how many empty strings and missing values compose this ensembl gene ids without hgnc symbol to see if there are any duplicates that have hgnc symbol representing more than 1 ensembl gene id.

The number of empty strings for duplicated hgnc_symbol

[1] 451



The number of missing values for duplicated hgnc_symbol

[1] 2257

When the number of missing value and the number of emtpy strings are summed and compared against the number of duplicated HGNC symbol, the logical conditional outputs FALSE.

[1] FALSE

There is 1 HGNC symbol duplicate that is neither an empty string nor a missing value.

[1] 1

And it is this!

And the different ensembl IDs that correspond to the symbol “MIR3615”

Searching the two ensembl gene id at the http://grch37.ensembl.org/ tells me that one is forward strand and the another is reverse strand.

I’ve decided to keep both of the MIR3614 rows because the expression level was different between the forward and reverse strand, interestingly. And based on my understanding from molecular biology classes, the RNA polymerase does not know whether the genes should be transcribed in either one of the strands (i.e. in either two directions), although RNA polymerase does prematurely halt when it is on the non-coding strand.

Now for the problem of whether to keep or filter the other 2708 expression values that do not map to HGNC symbol, I was introduced to HGNChelper package to check whether the external gene names have better up-to-date recommended names.

And out of those expression values, only 82 of them had recommended names.

[1] 82
Human gene symbols should be all upper-case except for the 'orf' in open reading frames. The case of some letters was corrected.x contains non-approved gene symbols



I’ve decided to keep all the 2708 expression values, as they are a sizable chunk of my data and are those genes that may not have their functions assigned but are expressed up to certain degree in my samples without getting discarded in the filter step.

I’ve decided to keep an extra column for external_gene_name attribute for all my expression value rows, and also include the recommended names in the suggested.symbol column, based on external_gene_name column.

Unfortunately, this means that the final result of my dataset would have many genes that are missing the HUGO gene symbol. And one of my genes MIR3614 has non-unique HUGO gene symbol.

Here is a head view of my final curated data.

Final Coverage of my Dataset

The Dimension of my Final Data Frame of Normalized Expressions

[1] 17120    17

The final coverage of my dataset has 17120 genes, with just one duplicate gene. And it has 4 different treatment groups, where each group have 3 biological replicates.

There are 2708 genes without mapped HUGO gene symbol, but have external names that allow one to identify the gene.

References

Huang, Alexander C, Michael A Postow, Robert J Orlowski, Rosemarie Mick, Bertram Bengsch, Sasikanth Manne, Wei Xu, et al. 2017. “T-Cell Invigoration to Tumour Burden Ratio Associated with Anti-Pd-1 Response.” Nature 545 (7652). Nature Publishing Group: 60.

Lipp, Jesse. 2016. “Why Sequencing Data Is Modeled as Negative Binomial.” Bioramble. https://bioramble.wordpress.com/2016/01/30/why-sequencing-data-is-modeled-as-negative-binomial/.

Robinson, Mark D, and Alicia Oshlack. 2010. “A Scaling Normalization Method for Differential Expression Analysis of Rna-Seq Data.” Genome Biology 11 (3). BioMed Central: R25.

Robinson, M D, D J McCarthy, and G K Smyth. 2010. “EdgeR: A Bioconductor Package for Differential Expression Analysis of Digital Gene Expression Data.” Bioinformatics 26 (1): 139–40. https://doi.org/10.1093/bioinformatics/btp616.

LS0tCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IHBhcGVyCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAKYmlibGlvZ3JhcGh5OiBsaWJyYXJ5LmJpYgotLS0KIyBSTkEgU2VxIFByZS1Qcm9jZXNzaW5nCioqUGVyaXBoZXJhbCBCbG9vZCBDRDgrIFQgY2VsbCBpbiBQcmUtQW50aS1QRC0xIEFudGlib2R5IHZzIFBvc3QtQW50aS1QRC0xIEFudGlib2R5IFRyZWF0ZWQgTWVsYW5vbWEgUGF0aWVudHMqKgoKQnkgRG9uZyBIb29uIEhhbgpCQ0I0MjAgMjAyMAo8YnI+CipSZWZlcmVuY2VzIGFyZSBhdCB0aGUgYm90dG9tIG9mIHRoZSBodG1sIQoKIyMgSW50cm9kdWN0b3J5IFF1ZXN0aW9ucyB7LnRhYnNldH0KCiMjIyBXaHkgaXMgdGhlIGRhdGFzZXQgb2YgaW50ZXJlc3QgdG8geW91PyB7LnRhYnNldH0KCkkgYW0gaW50ZXJlc3RlZCBpbiBpbW11bm9sb2d5LCBlc3BlY2lhbGx5IGluIFQgY2VsbHMsIHdoaWNoIGFyZSBkcml2aW5nIHRoZSBuZXh0IGdlbmVyYXRpb24gaW1tdW5vdGhlcmFweSB0cmVhdG1lbnRzIGZvciBjYW5jZXIuIAoKSW1tdW5vY2hlY2twb2ludCBpbmhpYml0b3JzIHN1Y2ggYXMgQ1RMQS00IGFuZCBQRC0xIGluaGliaXRvcnMgaGF2ZSBiZWVuIHBhcnRpY3VsYXJseSBzdWNjZXNzZnVsLCB3aGljaCBpbmhpYml0IHRoZSBicmVhayBvZiBhY3RpdmF0ZWQgVCBjZWxscy4gVW5mb3J0dW5hdGVseSwgYWx0aG91Z2ggdGhleSBoYXZlIGJlZW4gc3VjY2Vzc2Z1bCwgdGhleSBkaWQgbm90IGFjaGlldmUgdGhlIHNhbWUgZGVncmVlIG9mIHN1Y2Nlc3MgaW4gZXZlcnkgcGF0aWVudHMuCgpUaGUgZGF0YXNldCBmcm9tIHRoaXMgc3R1ZHkgd291bGQgYWxsb3cgbWUgdG8gcHJvYmUgaW50byB0aGUgdHJhbnNjcmlwdG9tZXMgb2YgdGhvc2UgYnJlYWstaW5oaWJpdGVkIGFjdGl2YXRlZCBDRDheK14gY3l0b3RveGljIFQgY2VsbHMgdnMgbm9ybWFsIGFjdGl2YXRlZCBDRDheK14gY3l0b3RveGljIFQgY2VsbHMuIFRoaXMgd291bGQgaGVscCBtZSB0byBoeXBvdGhlc2l6ZSB0aGUgZGlmZmVyZW50IG1lY2hhbmlzbXMgb2Ygd2h5IHRob3NlIGJyZWFrLWluaGliaXRlZCBDRDheK14gVHMgYXJlIG1vcmUgZWZmZWN0aXZlIGFnYWluc3QgY2FuY2VyIHZzIG5vcm1hbCBhY3RpdmF0ZWQgQ0Q4XiteIFRzLCBhbmQgcG9zc2libHkgd2h5IHRoaXMgdGhlcmFweSBtYXkgbm90IGJlIHJlc3BvbmRpbmcgYWdhaW5zdCBjZXJ0YWluIHBhdGllbnRzLgoKVW5mb3J0dW5hdGVseSwgdGhpcyBkYXRhc2V0IGRvZXMgbm90IGluZGljYXRlIHdoZXRoZXIgdGhlIHBhdGllbnQgaGFzIHN1cnZpdmVkIG9yIHN1Y2N1bWJlZCB0byB0aGUgY2FuY2VyLCBtb3N0IGxpa2VseSBkdWUgdG8gcHJpdmFjeSBpc3N1ZXMuCgoKIyMjIENvbnRyb2wgYW5kIFRlc3QgY29uZGl0aW9ucyBvZiB0aGUgZGF0YXNldD8gey50YWJzZXR9CgoqKlBhdGllbnRzIHdpdGggc3RhZ2UgSVYgbWVsYW5vbWEqKiB3ZXJlIGVucm9sbGVkIGZvciB0cmVhdG1lbnQgd2l0aCAqKnBlbWJyb2xpenVtYWIgKHBlbWJybyksIGFudGktUEQtMSBhbnRpYm9keSAoMiBtZyBrZ14tMSBieSBpbmZ1c2lvbiBldmVyeSAzIHdlZWtzKSoqLiBBZnRlciByZWNlaXZpbmcgdGhlaXIgY29uc2VudHMsIHBlcmlwaGVyYWwgYmxvb2Qgd2FzIG9idGFpbmVkIGJlZm9yZSB0cmVhdG1lbnQgYW5kIGJlZm9yZSBlYWNoIHBlbWJybyBpbmZ1c2lvbiBldmVyeSB3ZWVrcyBmb3IgMTIgd2Vla3MuIFtAaHVhbmcyMDE3dF0KCkZvciBSTkEgc2VxdWVuY2luZyBleHBlcmltZW50cywgdG90YWwgQ0Q4IFQgY2VsbHMgd2VyZSBzb3J0ZWQgdXNpbmcgYSBkdW1wL2RlYWQtQ0QzXiteIENEOF4rXiBnYXRpbmcgc3RyYXRlZ3ksIGJ5IEJEIEFyaWEgU29ydGVyIFtAaHVhbmcyMDE3dF0uIER1bXAgaGVyZSBtZWFucyB0aGUgZXhjbHVzaW9uIGNoYW5uZWwgd2hpY2ggaXMgdXNlZCBmb3Igc3RhaW5pbmcgZXZlcnl0aGluZyB5b3UgZG8gbm90IHdhbnQuCgpTbyB0aGUgKipjb250cm9scyoqIGFyZSB0aGUgUk5BIHNlcXVlbmNpbmcgb2YgdG90YWwgQ0Q4IFQgY2VsbHMgYmVmb3JlIHBlbWJybyBpbmZ1c2lvbi4gCgpUaGUgKip0ZXN0cyoqIGFyZSB0aGUgUk5BIHNlcXVlbmNpbmcgb2YgdG90YWwgQ0Q4IFQgY2VsbHMgMyB3ZWVrcyBhZnRlciBlYWNoIHBlbWJybyBpbmZ1c2lvbi4gCgpPdmVyYWxsIHRoZSBzYW1wbGVzIGFyZSBkaXZpZGVkIGludG8gY3ljbGUgMSwgMiwgMywgNCwgYXMgcGVtYnJvIHdhcyBpbmplY3RlZCBhdCBXZWVrIDAsIDMsIDYsIDksIGFuZCB0aGUgYmxvb2Qgd2FzIGRyYXduIGJlZm9yZSBwZW1icm8gaW5qZWN0aW9uIGF0IFdlZWsgMCwgMywgNiwgOSwgMTIuIAoKKipQcmV0cmVhdG1lbnQgc2FtcGxlcyoqIGFyZSB3ZWVrIDAgcHJlLXRyZWF0bWVudCBwZXJpcGhlcmFsIGJsb29kIENEOCBUIGNlbGxzLiBUaGVzZSBhcmUgdGhlIGNvbnRyb2xzLgoKKipDeWNsZSAxIHNhbXBsZXMqKiBhcmUgd2VlayAzIHBlcmlwaGVyYWwgYmxvb2QgQ0Q4IFQgY2VsbHMgYWZ0ZXIgdGhlIHdlZWsgMCBwZW1icm8gaW5qZWN0aW9uLgoKKipDeWNsZSAyIHNhbXBsZXMqKiBhcmUgd2VlayA2IHBlcmlwaGVyYWwgYmxvb2QgQ0Q4IFQgY2VsbHMgYWZ0ZXIgdGhlIHdlZWsgMCwgMyBwZW1icm8gaW5qZWN0aW9uLgoKKipDeWNsZSAzIHNhbXBsZXMqKiBhcmUgd2VlayA5IHBlcmlwaGVyYWwgYmxvb2QgQ0Q4IFQgY2VsbHMgYWZ0ZXIgdGhlIHdlZWsgMCwgMywgNiBwZW1icm8gaW5qZWN0aW9uLgoKKipDeWNsZSA0IHNhbXBsZXMqKiBhcmUgd2VlayAxMiBwZXJpcGhlcmFsIGJsb29kIENEOCBUIGNlbGxzIGFmdGVyIHRoZSB3ZWVrIDAsIDMsIDYsIDkgcGVtYnJvIGluamVjdGlvbi4KCioqQ3ljbGUgMiBzYW1wbGVzIHdlcmUgbm90IGluY2x1ZGVkKiogaW4gdGhpcyBhbmFseXNpcywgYmVjYXVzZSBvdGhlciBzYW1wbGVzIGFsbCBoYWQgMyByZXBsaWNhdGVzIChmcm9tIDMgcGF0aWVudHMpIHdoZXJlYXMgdGhlcmUgd2FzIG9ubHkgb25lIGN5Y2xlIDIgc2FtcGxlIChmcm9tIGEgc2luZ2xlIHBhdGllbnQpLgoKIyMjIEdTRSBPYmplY3Qgey50YWJzZXR9CgpMb2FkaW5nIExpYnJhcmllcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KbGlicmFyeShlZGdlUikKbGlicmFyeShHRU9xdWVyeSkKbGlicmFyeShkcGx5cikKbGlicmFyeShrbml0cikKbGlicmFyeShiaW9tYVJ0KQpgYGAKCgpMb2FkaW5nIGluIHRoZSBHU0UgYnkgdXNpbmcgR0VPcXVlcnkgcGFja2FnZSAmIEV4dHJhY3RpbmcgUmVsZXZhbnQgSW5mb3JtYXRpb24KYGBge3IgY2h1bmssIGNvbGxhcHNlPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGVjaG8gPSBUUlVFLCByZXN1bHRzID0gJ2FzaXMnfQojIExvYWRpbmcgaW4gdGhlIERhdGEKR1NFOTY1NzggPC0gZ2V0R0VPKCJHU0U5NjU3OCIsR1NFTWF0cml4PUZBTFNFKQoKCiMgUm91Z2hseSB3aGF0IGtpbmQgb2YgZXhwZXJpbWVudCB3YXMgdGhpcy4Ka2FibGUoZGF0YS5mcmFtZShPdmVyYWxsLkRlc2lnbiA9IEdTRTk2NTc4QGhlYWRlciRvdmVyYWxsX2Rlc2lnbikpCmthYmxlKGRhdGEuZnJhbWUoRXhwZXJpbWVudC5TdW1tYXJ5ID0gR1NFOTY1NzhAaGVhZGVyJHN1bW1hcnkpKQoKY3VycmVudF9ncGwgPC0gbmFtZXMoR1BMTGlzdChHU0U5NjU3OCkpWzFdICAgIyBHUEwyMzE3NwpjdXJyZW50X2dwbF9pbmZvIDwtIE1ldGEoZ2V0R0VPKGN1cnJlbnRfZ3BsKSkKCmthYmxlKGRhdGEuZnJhbWUoR1BMLlRpdGxlID0gY3VycmVudF9ncGxfaW5mbyR0aXRsZSwgU3VibWlzc2lvbiA9IGN1cnJlbnRfZ3BsX2luZm8kc3VibWlzc2lvbl9kYXRlLCAKICAgICAgICAgICBMYXN0LlVwZGF0ZSA9IGN1cnJlbnRfZ3BsX2luZm8kbGFzdF91cGRhdGVfZGF0ZSwKICAgICAgICAgICBPcmdhbmlzbSA9IGN1cnJlbnRfZ3BsX2luZm8kb3JnYW5pc20sIE51bWJlci5vZi5TZXJpZXMgPSBsZW5ndGgoY3VycmVudF9ncGxfaW5mbyRzZXJpZXNfaWQpLCAKICAgICAgICAgICBOdW1iZXIub2YuU2FtcGxlcyA9IGxlbmd0aChjdXJyZW50X2dwbF9pbmZvJHNhbXBsZV9pZCkgKSkKCmBgYAoKCjo6OgoKCiMjIyBSYXcgQ291bnRzIE1hdHJpeCB7LnRhYnNldH0KCkxvYWRpbmcgaW4gdGhlIFJhdyBDb3VudHMgTWF0cml4CgpUd28gY291bnQgbWF0cml4ZXM6IG5vcm1hbGl6ZWQgJiByYXcgY291bnRzLCB1c2luZyB0aGUgcmF3IGNvdW50cyBtYXRyaXgKYGBge3J9CnNmaWxlcyA8LSBnZXRHRU9TdXBwRmlsZXMoIkdTRTk2NTc4IikKZm5hbWVzID0gcm93bmFtZXMoc2ZpbGVzKQojIFsxXSAiL2hvbWUvcnN0dWRpby9HU0U5NjU3OC9HU0U5NjU3OF9BSF9QQk1DX1JOQXNlcV9ub3JtY291bnRzLnR4dC5neiIKIyBbMl0gIi9ob21lL3JzdHVkaW8vR1NFOTY1NzgvR1NFOTY1NzhfQUhfUEJNQ19STkFzZXFfcmF3Y291bnRzLnR4dC5neiIgCgojIExvYWRpbmcgaW4gdGhlIHJhdyBjb3VudCBtYXRyaXgKY2Q4X2V4cCA8LXJlYWQuZGVsaW0oZm5hbWVzWzJdLGhlYWRlcj1UUlVFLCBjaGVjay5uYW1lcyA9IEZBTFNFKQpgYGAKCkZpcnN0IDYgcm93cyBvZiBSYXcgQ291bnRzIE1hdHJpeApgYGB7cn0KaGVhZChjZDhfZXhwKQpgYGAKPGJyPgpEaW1lbnNpb24gb2YgdGhlIFJhdyBDb3VudHMgTWF0cml4CmBgYHtyfQpkaW0oY2Q4X2V4cCkKIyBbMV0gMjgzODMgICAgMTYKIyAyODM4MyBnZW5lcyAmIDEzIG91dCBvZiAxNiBjb2x1bW5zIGFyZSBzYW1wbGVzOyBvdGhlciAzIGFyZSBJRCwgZ2VuZSBjb29yZGluYXRlLCBnZW5lIHN5bWJvbC4KCiMgY29sbmFtZXMoY2Q4X2V4cCkKIyBbMV0gImlkIiAgICAgICAgICAgICAiZ2VuZUNvb3JkaW5hdGUiICJnZW5lU3ltYm9sIiAgICAgIlJfUzQxNiIgICAgICAgICAiUl9TNDE3IiAgICAgICAgICJSX1M0MTgiICAgICAgICAKIyBbN10gIlJfUzQxOSIgICAgICAgICAiUl9TNDIwIiAgICAgICAgICJSX1M0MjYiICAgICAgICAgIlJfUzQyNyIgICAgICAgICAiUl9TNDI4IiAgICAgICAgICJSX1M0MjkiICAgICAgICAKIyBbMTNdICJSX1M0MzAiICAgICAgICAgIlJfUzQzMSIgICAgICAgICAiUl9TNDMyIiAgICAgICAgICJSX1M0MzMiICAKCiMgUmVtb3Zpbmcgb2JqZWN0cyBmb3Igc2FuaXR5IHNha2UKCnJtKCBsaXN0ID0gRmlsdGVyKCBleGlzdHMsIGMoInNmaWxlcyIsICJmbmFtZXMiKSApICkKCmBgYAo8YnI+CldoYXQgZWFjaCBHU01zIGNvcnJlc3BvbmQgdG8KYGBge3J9CmthYmxlKHJiaW5kKGRhdGEuZnJhbWUodChuYW1lcyhHU01MaXN0KEdTRTk2NTc4KSkpKSwgZGF0YS5mcmFtZSh0KGNvbG5hbWVzKGNkOF9leHApWzQ6MTZdKSkpKQpgYGAKPGJyPgoqKkNvbXByZWhlbnNpdmUgU2FtcGxlIEluZm9ybWF0aW9uIE1hdHJpeCoqIC0+IE5vdCBpbmNsdWRpbmcgUl9TNDE4IEN5Y2xlMiB0cmVhdG1lbnQgaW4gdGhlIGRvd25zdHJlYW0gYW5hbHlzaXMsIGJlY2F1c2UgdGhlcmUgaXMgbm8gYmlvbG9naWNhbCByZXBsaWNhdGUgZm9yIHRoaXMgQ3ljbGUyIHRyZWF0bWVudCBSTkEtc2VxIGV4cGVyaW1lbnQKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBXaGF0IGRvIGVhY2ggb2YgdGhlc2UgUl9TNHh4IG1lYW4/IGkuZS4gd2hhdCBkbyBlYWNoIG9mIHRoZXNlIHNhbXBsZXMgcmVwcmVzZW50PyAtLS0tCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCnNhbXBsZS5pbmZvLm1hdHJpeCA8LSBkYXRhLmZyYW1lKCkKCiMgaSB1bmRlciBHU0U5NjU3OEBnc21zIGlzIGEgR1NFIG9iamVjdCwgd2hpY2ggY2FuIGJlIHByb2JlZCB1c2luZyBNZXRhKCkgZnVuY3Rpb24KIyBVc2UgZm9yIGxvb3AgdG8gcHJvYmUgZWFjaCBvZiB0aGUgMTMgc2FtcGxlcwpmb3IoaSBpbiBHU0U5NjU3OEBnc21zKXsKICBzYW1wbGUuaW5mby5tYXRyaXggPC0gcmJpbmQoc2FtcGxlLmluZm8ubWF0cml4LAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoTWV0YShpKSR0aXRsZSwgTWV0YShpKSRjaGFyYWN0ZXJpc3RpY3NfY2gxWzNdLE1ldGEoaSkkY2hhcmFjdGVyaXN0aWNzX2NoMVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1ldGEoaSkkY2hhcmFjdGVyaXN0aWNzX2NoMVs1XSwgTWV0YShpKSRsaWJyYXJ5X3N0cmF0ZWd5LCBNZXRhKGkpJGluc3RydW1lbnRfbW9kZWwpKQp9CmNvbG5hbWVzKHNhbXBsZS5pbmZvLm1hdHJpeCkgPC0gYygiVGl0bGUiLCJUcmVhdG1lbnQiLCAiUGF0aWVudCBBZ2UiLCAiRGlzZWFzZSBTdGF0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRGF0YSBUeXBlIiwgIkluc3RydW1lbnQiKQojIHNhbXBsZS5pbmZvLm1hdHJpeAoKIyBEZWNpZGVkIG5vdCB0byBpbmNsdWRlIFJfUzQxOCBDeWNsZTIgdHJlYXRtZW50IGluIHRoZSBkb3duc3RyZWFtIGFuYWx5c2lzLCBiZWNhdXNlCiMgdGhlcmUgaXMgbm8gcmVwbGljYXRlIGZvciB0aGlzIEN5Y2xlMiB0cmVhdG1lbnQgUk5BLXNlcSBleHBlcmltZW50CnNhbXBsZS5pbmZvLm1hdHJpeCA8LSBzYW1wbGUuaW5mby5tYXRyaXhbLTMsXQpjZDhfZXhwIDwtIGRwbHlyOjpzZWxlY3QoLmRhdGEgPSBjZDhfZXhwLCAtUl9TNDE4KQojIGhlYWQoc2FtcGxlLmluZm8ubWF0cml4KQojIGhlYWQoY2Q4X2V4cCkKCgojIExldCdzIGNyZWF0ZSBhIG1vcmUgZGVzY3JpcHRpdmUgbGFiZWwgZm9yIGVhY2ggb2YgdGhlIHNhbXBsZXMKCmRlc2NyaXB0aXZlLmxhYmVsIDwtIGMoInB0LkEuUHJlVHJlYXQiLCAicHQuQS5DeWNsZTEiLCAicHQuQS5DeWNsZTMiLCAicHQuQS5DeWNsZTQiLAogICAgICAgICAgICAgICAgICAgICAgICJwdC5CLlByZVRyZWF0IiwgInB0LkIuQ3ljbGUxIiwgInB0LkIuQ3ljbGUzIiwgInB0LkIuQ3ljbGU0IiwKICAgICAgICAgICAgICAgICAgICAgICAicHQuQy5QcmVUcmVhdCIsICJwdC5DLkN5Y2xlMSIsICJwdC5DLkN5Y2xlMyIsICJwdC5DLkN5Y2xlNCIpCgpzYW1wbGUuaW5mby5tYXRyaXggJT4lIG11dGF0ZShMYWJlbCA9IGRlc2NyaXB0aXZlLmxhYmVsKSAtPiBzYW1wbGUuaW5mby5tYXRyaXgKCnNhbXBsZS5pbmZvLm1hdHJpeCAlPiUgCiAgbXV0YXRlKFBhdGllbnQgPSBzdHJpbmdyOjpzdHJfbWF0Y2goc3RyaW5nID0gc2FtcGxlLmluZm8ubWF0cml4JExhYmVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiKD88PVxcLikoLiopKD89XFwuKSIpWywxXSkgJT4lCiAgbXV0YXRlKFRyZWF0bWVudCA9IHN0cmluZ3I6OnN0cl9tYXRjaChzdHJpbmcgPSBzYW1wbGUuaW5mby5tYXRyaXgkTGFiZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIig/PD1wdFxcLltBLXpdXFwuKSguKikiKVssMV0pIC0+IHNhbXBsZS5pbmZvLm1hdHJpeAoKa2FibGUoc2FtcGxlLmluZm8ubWF0cml4KQoKIyBMZXRzIGNoYW5nZSB0aGUgQ291bnQgTWF0cml4IFNhbXBsZSBuYW1lcyB0byB0aGUgbW9yZSBkZXNjcmlwdGl2ZSBuYW1lcyBhcyB3ZWxsCgpjb2xuYW1lcyhjZDhfZXhwKVs0OjE1XSA8LSBzYW1wbGUuaW5mby5tYXRyaXgkTGFiZWwKCiMgUmVtb3ZpbmcgZGVzY3JpcHRpdmUubGFiZWwgZm9yIHNhbml0eSBzYWtlCgpybSggbGlzdCA9IEZpbHRlciggZXhpc3RzLCBjKCJkZXNjcmlwdGl2ZS5sYWJlbCIsICJpIikgKSApCmBgYAoKCgoKCiMjIyBDb250YWN0IEluZm9ybWF0aW9uIGFuZCBEYXRhIFByb2Nlc3NpbmcgJiBFeHRyYWN0aW9uIFByb3RvY29sey50YWJzZXR9CgpDb250YWN0IEluZm9ybWF0aW9uCmBgYHtyfQprYWJsZShkYXRhLmZyYW1lKGhlYWQoTWV0YShHU0U5NjU3OCkpKSkKYGBgCkRhdGEgUHJvY2Vzc2luZyBQcm90b2NvbCBmb3IgYWxsIFNhbXBsZXMgZnJvbSBGYXN0cSB0byBSYXcgQ291bnRzCmBgYHtyfQpqID0gMApEYXRhX1Byb2Nlc3NpbmcgPC0gbGlzdCgpCkV4dHJhY3Rpb25fUHJvdG9jb2wgPC0gbGlzdCgpCmZvcihpIGluIEdTRTk2NTc4QGdzbXMpewogIGogPSBqICsgMQogIERhdGFfUHJvY2Vzc2luZ1tbal1dIDwtIE1ldGEoaSkkZGF0YV9wcm9jZXNzaW5nCiAgRXh0cmFjdGlvbl9Qcm90b2NvbFtbal1dIDwtIE1ldGEoaSkkZXh0cmFjdF9wcm90b2NvbF9jaDEKfQp1bmxpc3QodW5pcXVlKERhdGFfUHJvY2Vzc2luZykpCgojIFtbMV1dCiMgWzFdICJUaGUgZmFzdHFzIHdlcmUgYWxpZ25lZCB1c2luZyBTVEFSIDIuNS4yYSBhbmQgaGcxOSIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiMgWzJdICJUaGUgYWxpZ25lZCBmaWxlcyB3ZXJlIHByb2Nlc3NlZCB1c2luZyBQT1JUIGdlbmUtYmFzZWQgbm9ybWFsaXphdGlvbiAKIyAoIGh0dHBzOi8vZ2l0aHViLmNvbS9pdG1hdC9Ob3JtYWxpemF0aW9uICkiCiMgWzNdICJUaGUgZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiB3YXMgZG9uZSB3aXRoIGxpbW1hIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiMgWzRdICJHZW5vbWVfYnVpbGQ6IGhnMTkiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiMgWzVdICJTdXBwbGVtZW50YXJ5X2ZpbGVzX2Zvcm1hdF9hbmRfY29udGVudDogUmF3IGNvdW50cyBhbmQgbm9ybWFsaXplZCBjb3VudHMiICAgICAKYGBgCgpFeHRyYWN0aW9uIFByb3RvY29sIGZvciBhbGwgU2FtcGxlcwpgYGB7cn0KdW5saXN0KHVuaXF1ZShFeHRyYWN0aW9uX1Byb3RvY29sKSkKCiMgW1sxXV0KIyBbMV0gIlJOQSB3YXMgaXNvbGF0ZWQgdXNpbmcgdGhlIFFpYWdlbiBSTmVhc3kgbWljcm8ga2l0ICgjNzQwMzQpIGFjY29yZGluZyB0byB0aGUgbWFudWZhY3R1cmVyJ3MgCiMgcHJvdG9jb2wiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAojIFsyXSAiUk5BLXNlcSBsaWJyYXJpZXMgd2VyZSBwcmVwYXJlZCB1c2luZyB0aGUgU01BUlRlciBTdHJhbmRlZCBUb3RhbCBSTkEtU2VxIEtpdCBmb3IgUGljbyBJbnB1dCBNYW1tYWxpYW4gCiMgZnJvbSBDbG9uZXRlY2ggYWNjb3JkaW5nIHRvIHRoZSBtYW51ZmFjdHVyZXIncyBwcm90b2NvbCAoIzYzNTAwNykiCiMgWzNdICJUaGUgbGlicmFyaWVzIHdlcmUgc2VxdWVuY2VkIG9uIGFuIElsbHVtaW5hIE5leHRTZXEgbWFjaGluZSB1c2luZyBhIDMwMCBjeWNsZSBoaWdoIG91dHB1dCAKIyBmbG93IGNlbGwgKCMxNTA1NzkyOSkiICAgCgojIFJlbW92aW5nIGosIGksIERhdGFfUHJvY2Vzc2luZywgJiBFeHRyYWN0aW9uX1Byb3RvY29sCgpybShpLCBqLCBEYXRhX1Byb2Nlc3NpbmcsIEV4dHJhY3Rpb25fUHJvdG9jb2wpCgoKYGBgCiMjCgoKCgoKIyMgT3V0bGllcnMsIFJlcGxpY2F0ZXMgJiBEdXBsaWNhdGVzIHsudGFic2V0fQoKIyMjIEdlbmUgRHVwbGljYXRlcyB7LnRhYnNldH0KCkR1cGxpY2F0ZXMgd2VyZSBoYW5kbGVkIHRoZSBmb2xsb3dpbmcgd2F5LgoKRGltZW5zaW9uIG9mIHRoZSBSYXcgQ291bnQgTWF0cml4CmBgYHtyfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgTm93IENsZWFuaW5nIHRoZSBEYXRhIC0tLS0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgoKIyBIb3cgbWFueSB1bmlxdWUgZ2VuZXMgZG8gd2UgaGF2ZT8KIyBBcmUgdGhlcmUgYW55IG5vbi1nZW5lcyBpbiBvdXIgZGF0YXNldD8gSWYgc28sIHdoYXQgYXJlIHRoZXk/CiMgQ2FuIHdlIGV4Y2x1ZGUgdGhlbT8KCmRpbShjZDhfZXhwKQojIFsxXSAyODM4MyAgICAxNQojIDI4MzgzIGdlbmVzICYgMTIgb3V0IG9mIDE1IGNvbHVtbnMgYXJlIHNhbXBsZXM7IG90aGVyIDMgYXJlIElELCBnZW5lIGNvb3JkaW5hdGUsIGdlbmUgc3ltYm9sLgojIHRoZXJlIDQgdHJpcGxldCByZXBsaWNhdGVzIHNvIDEyIHNhbXBsZXMgaW4gdG90YWw6IFByZS10cmVhdG1lbnQsIEN5Y2xlIDEsIEN5Y2xlIDMsIEN5Y2xlIDQgCmBgYApUaGVyZSBhcmUgMjgzODMgZmVhdHVyZXMgKGkuZS4gZ2VuZXMvbm9uZ2VuZXMpICYgMTIgb3V0IG9mIDE1IGNvbHVtbnMgYXJlCnNhbXBsZXM7IG90aGVyIDMgYXJlIElELCBnZW5lIGNvb3JkaW5hdGUsIGdlbmUgc3ltYm9sLgo8YnI+ClRoaXMgcmF3IGNvdW50IG1hdHJpeCBjb25zaXN0cyBvZiA0IHRyaXBsZXQgcmVwbGljYXRlcyBzbyAxMiBzYW1wbGVzIGluIAp0b3RhbDogUHJlLXRyZWF0bWVudCwgQ3ljbGUgMSwgQ3ljbGUgMywgQ3ljbGUgNCAKPGJyPgo8YnI+CkkndmUgY3JlYXRlZCB0aGUgdGFibGUgb2Ygcm93IGNvdW50cyBmb3IgZWFjaCBvZiB0aGUgImdlbmUiIG5hbWUsIHVzaW5nCmNvZGUgbGVhcm50IGZyb20gdGhlIGNsYXNzLiBUaGlzIGlzIHRvIHByb2JlIHRoZSBnZW5lIGR1cGxpY2F0ZXMgaW4gbXkKZGF0YS4KYGBge3J9CiMgaGVhZChjZDhfZXhwKQoKIyBDcmVhdGUgYSB0YWJsZSBvZiByb3cgY291bnRzIGZvciBlYWNoIGZhY3RvciAoaS5lLiBnZW5lIG5hbWUgb3IgbWF5YmUgc3RoIGVsc2UpIGluIHRoZSBnZW5lU3ltYm9sIGNvbHVtbiAKc3VtbWFyaXplZF9nZW5lX2NvdW50cyA8LSBzb3J0KHRhYmxlKGNkOF9leHAkZ2VuZVN5bWJvbCksZGVjcmVhc2luZyA9IFRSVUUpCgojIExldHMgb25seSBpbmNsdWRlIHRob3NlIGZhY3RvcnMgd2l0aCBtb3JlIHRoYW4gMSBjb3VudAprYWJsZSh0KHN1bW1hcml6ZWRfZ2VuZV9jb3VudHNbd2hpY2goc3VtbWFyaXplZF9nZW5lX2NvdW50cz4xKVsxOjEwXV0pKQojIFlfUk5BICAgICAgIFUzICAgICAgc25vVTEzICAgTWV0YXpvYV9TUlAgICBTTk9SQTQwICAgICA3U0sgICAgICAgICBVMSAgICAgICAgICBVNiAgICAgU05PUkEzMSAgICAgU05PUkE3MCAKIyAxNzQgICAgICAgICAxOSAgICAgIDkgICAgICAgIDggICAgICAgICAgICAgNyAgICAgICAgICAgNiAgICAgICAgICAgNCAgICAgICAgICAgNCAgICAgIDMgICAgICAgICAgIDMgCmBgYApXaHkgZG8gY2VydGFpbiBmYWN0b3JzIGxpa2UgWV9STkEgYXBwZWFyIG1vcmUgdGhhbiBvbmNlIGluIHRoZSBnZW5lIHJvdz8gCkxldCdzIGNoZWNrIGl0IG91dCB1c2luZyBoZWFkKCkgYW5kIGxvZ2ljYWwgc3Vic2V0dGluZyB0byBzZWxlY3QgdGhvc2Ugcm93cyB3aXRoICJZX1JOQSIuCmBgYHtyfQpoZWFkKGNkOF9leHBbY2Q4X2V4cCRnZW5lU3ltYm9sID09ICJZX1JOQSIsXSlbLDE6Nl0KYGBgCgpTb21lIGZhY3RvcnMgbGlrZSBZX1JOQSBhcHBlYXJzIG11bHRpcGxlIHRpbWVzIGJlY2F1c2UgdGhlcmUgYXJlIGRpZmZlcmVudCBZX1JOQSBhdCBkaWZmZXJlbnQgY2hyb21vc29tYWwgcmVnaW9ucy4KWSBSTkFzIGFyZSBzbWFsbCBub24tY29kaW5nIFJOQXMsIFNOT1IgYXJlIHNtYWxsIG51Y2xlb2xhciBSTkEsIGFuZCBVcyBhcmUgc21hbGwgbnVjbGVhciBSTkEuCjxicj4KPGJyPgpGcm9tIHRoZSBub3RlcyBJJ3ZlIHRvb2sgZHVyaW5nIGxlY3R1cmUgYW5kIG15IG9waW5pb24sIHRoZXJlIGlzIG5vIG5lZWQgdG8gZmlsdGVyIHRoZW0gb3V0LCBzaW5jZSB0aGV5IGFyZSB1bmlxdWUgZmVhdHVyZXMgb2YgdGhlIGNlbGxzIHRoYXQKbWFwIHRvIGRpZmZlcmVudCBjaHJvbW9zb21hbCByZWdpb25zLgo8YnI+Cjxicj4KQnV0IHdlIGRvIG5lZWQgdG8gZmlsdGVyIG91dCB3ZWFrbHkgZXhwcmVzc2VkIGFuZCBub25pbmZvcm1hdGl2ZSAobm9uLWFsaWduZWQpIGZlYXR1cmVzLCBhbGwgb2Ygd2hpY2ggY2FuIGJlIGRvbmUgaW4gZWRnZVIuCgojIyMgRmlsdGVyaW5nIG91dCBPdXRsaWVycyAoSG93IG1hbnkgd2VyZSBmaWx0ZXJlZCBvdXQpey50YWJzZXR9CgpHZW5lcyB3aXRoIHZlcnkgbG93IGNvdW50IGFjcm9zcyBhbGwgbGlicmFyaWVzIHByb3ZpZGUgdmVyeSBsaXR0bGUgZXZpZGVuY2UgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uLiBNb3Jlb3ZlciwKdGhlIGRpc2NyZXRlbmVzcyBvZiB0aGVzZSBsb3cgY291bnRzIGludGVyZmVyZXMgd2l0aCBzb21lIG9mIHRoZSBzdGF0aXN0aWNhbCBhcHByb3hpbWF0aW9ucyB1c2VkIGluIGVkZ2VSCnBhY2thZ2UgW0BSb2JpbnNvbjoyMDEwOkJpb2luZm9ybWF0aWNzOjE5OTEwMzA4XS4gVGh1cywgdGhlc2UgZ2VuZXMgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYXMgb3V0bGllcnMgYW5kCm5lZWQgdG8gYmUgZmlsdGVyZWQgb3V0IGJlZm9yZSBkb3duc3RyZWFtIGFuYWx5c2lzLgo8YnI+Cjxicj4KQSBnZW5lIGFsc28gc2hvdWxkIGJlIGZpbHRlcmVkIHdpdGggY291bnQtcGVyLW1pbGxpb24gKENQTSkgcmF0aGVyIHRoYW4gcmF3IGNvdW50cywgYXMgcmF3IGNvdW50cyBkbyBub3QgYWNjb3VudCBmb3IKZGlmZmVyZW5jZXMgaW4gbGlicmFyeSBzaXplcyBiZXR3ZWVuIHNhbXBsZXNbQFJvYmluc29uOjIwMTA6QmlvaW5mb3JtYXRpY3M6MTk5MTAzMDhdLgo8YnI+Cjxicj4KQmVmb3JlIGdldHRpbmcgc3RhcnRlZCwgbGV0J3MgZmlndXJlIG91dCB0aGUgZGVmaW5pdGlvbiBvZiBjb3VudHMgcGVyIG1pbGxpb24sIG9yIENQTS4KPGJyPgo8YnI+CiRDUE1fe2l9ID0gXGZyYWN7WF97aX19e059XGNkb3QgMTBeezZ9JAo8YnI+Cjxicj4KSGVyZSAkWF97aX0kIGlzIHRoZSBjb3VudCBmb3IgY2VydGFpbiBnZW5lIGFuZCAkXGZyYWN7Tn17MTBeezZ9fSQgaXMgdGhlIG51bWJlciBvZiBmcmFnbWVudHMgeW91IHNlcXVlbmNlZCBpbiB0aGUgbGlicmFyeSBwZXIgbWlsbGlvbi4KQnkgcHJvY2Vzc2luZyB0aGUgcmF3IGNvdW50IHRvIGNvdW50cyBwZXIgbWlsbGlvbiwgdGhlIGxpYnJhcnkgc2l6ZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNhbXBsZXMgY2FuIGJlIGFjY291bnRlZCBmb3IuCjxicj4KPGJyPgpSYXcgY291bnQgbWF0cml4IGlzIHR1cm5lZCBpbnRvIGNvdW50cyBwZXIgbWlsbGlvbiBtYXRyaXgsIGluIG9yZGVyIHRvIGZpbHRlciBvdXQgdGhlIGdlbmVzIHRoYXQgaGF2ZSBhYm5vcm1hbGx5IGxvdyBjb3VudHMuCmBgYHtyLCB3YXJuaW5nID0gRkFMU0V9CgojIEJlZm9yZSB0cmFuc2xhdGluZyByYXcgY291bnRzIGludG8gY291bnRzIHBlciBtaWxsaW9uIGJ5IHVzaW5nIGNwbSgpIGluIGVkZ2VSLAojIFdoYXQgaXMgY291bnRzIHBlciBtaWxsaW9uPwojIGh0dHBzOi8vaGFyb2xkcGltZW50ZWwud29yZHByZXNzLmNvbS8yMDE0LzA1LzA4L3doYXQtdGhlLWZwa20tYS1yZXZpZXctcm5hLXNlcS1leHByZXNzaW9uLXVuaXRzLwoKIyBGaXJzdCByZWZlciB0aGUgZWFjaCByZWFkLCBlaXRoZXIgc2luZ2xlLWVuZCBvciBwYWlyLWVuZGVkIHJlYWRzLCB0byByZXByZXNlbnQgYSBmcmFnbWVudCB0aGF0IHdhcyBzZXF1ZW5jZWQuCiMgQ291bnRzIHVzdWFsbHkgcmVmZXIgdG8gdGhlIG51bWJlciBvZiByZWFkcyB0aGF0IGFsaWduIHRvIGEgcGFydGljdWxhciBmZWF0dXJlLgojIEFuZCB0aGlzIGRlcGVuZHMgb24gdHdvIHRoaW5nczogKDEpIHRoZSBhbW91bnQgb2YgZnJhZ21lbnRzIHlvdSBzZXF1ZW5jZWQgKHRoaXMgaXMgcmVsYXRlZCB0byByZWxhdGl2ZSBhYnVuZGFuY2UpCiMgKDIpIHRoZSBsZW5ndGggb2YgdGhlIGZlYXR1cmUsIG9yIG1vcmUgYXBwcm9wcmlhdGVseSwgdGhlIGVmZmVjdGl2ZSBsZW5ndGgsIHRoZSBudW1iZXIgb2YgcG9zc2libGUgc3RhcnQgc2l0ZXMgYSAKIyBmZWF0dXJlIGNvdWxkIGhhdmUgZ2VuZXJhdGVkIGEgZnJhZ21lbnQgb2YgcGFydGljdWxhciBsZW5ndGgKCiMgQ291bnRzIHBlciBtaWxsaW9uIGFyZSBjb3VudHMgc2NhbGVkIGJ5IHRoZSBudW1iZXIgb2YgZnJhZ21lbnRzIHlvdSBzZXF1ZW5jZWQgKE4pIHRpbWVzIG9uZSBtaWxsaW9uCgojIFRyYW5zbGF0aW5nIGNvdW50cyBpbnRvIGNvdW50cyBwZXIgbWlsbGlvbiB1c2luZyBlZGdlUiBwYWNrYWdlIGZ1bmN0aW9uIGNwbQojID9jcG0KY3BtcyA8LSBjcG0oY2Q4X2V4cFssNDoxNV0pCgpyb3duYW1lcyhjcG1zKSA8LSBjZDhfZXhwWywxXQpoZWFkKGNwbXMpWywxOjZdCmBgYAoKPGJyPgpFZGdlUiByZWNvbW1lbmRzIHVzIHRvIHJlbW92ZSBmZWF0dXJlcyB3aXRob3V0IGF0IGxlYXN0IDEgcmVhZCBwZXIgbWlsbGlvbiAKaW4gbiBvZiB0aGUgc2FtcGxlcywgd2hlcmUgbiBpcyB0aGUgc2l6ZSBvZiB0aGUgc21hbGxlc3QgZ3JvdXAgb2YgcmVwbGljYXRlcwpUaGVyZSBhcmUgMyBzYW1wbGVzIG9mIGVhY2ggY3ljbGUgKGkuZS4gcHJlLXRyZWF0bWVudCwgY3ljbGUxLCBjeWNsZSAzLCBjeWNsZTQpCmlmIEkgZG8gbm90IGluY2x1ZGUgQ3ljbGUyIHRyZWF0bWVudCBzbyBuID0gMwo8YnI+Cjxicj4KVXNpbmcgdGhlIGFib3ZlIHByaW5jaXBsZSwgdGhlIGZpbHRlcmVkIGdlbmUgbWF0cml4IGlzIGdlbmVyYXRlZCwgYW5kIHRoZSBudW1iZXIgb2YgCmZlYXR1cmVzIGJldHdlZW4gYmVmb3JlIGFuZCBhZnRlciB0aGUgZmlsdGVyaW5nIGlzIHNob3duCmBgYHtyLCB3YXJuaW5nID0gRkFMU0V9CiMgRmlsdGVyaW5nIG91dCBsb3cgY291bnRzCmtlZXAgPC0gcm93U3VtcyhjcG1zID4xKSA+PTMgIyBTbyBuIGlzIDMgaGVyZSwgYW5kIGFsbCBmZWF0dXJlcyBtdXN0IGhhdmUgMSByZWFkIHBlciBtaWxsaW9uIGluIDMgb2YgdGhlIHNhbXBsZXMKCmNkOF9leHBfZmlsdGVyZWQgPC0gY2Q4X2V4cFtrZWVwLCBdCgojIGRpbShjZDhfZXhwKSAgICAgICAgICAgICMgWzFdIDI4MzgzICAgIDE1CiMgZGltKGNkOF9leHBfZmlsdGVyZWQpICAgIyBbMV0gMTcxMTggICAgMTUKYmVmb3JlX2FmdGVyIDwtIHQoZGF0YS5mcmFtZShCZWZvcmUgPSBkaW0oY2Q4X2V4cCksIEFmdGVyID0gZGltKGNkOF9leHBfZmlsdGVyZWQpKSkKY29sbmFtZXMoYmVmb3JlX2FmdGVyKSA8LSBjKCJOdW1iZXIgb2YgRmVhdHVyZXMiLCAiTnVtYmVyIG9mIENvbHVtbnMiKQprYWJsZShiZWZvcmVfYWZ0ZXIpCnJtKGJlZm9yZV9hZnRlcikKYGBgCioqSG93IG1hbnkgb3V0bGllcnMgd2VyZSByZW1vdmVkPyoqCjxicj4KMTEyNTYgZ2VuZXMgdGhhdCBoYWQgdmVyeSBsb3cgY291bnRzLCBpLmUsIG91dGxpZXJzLCBhY3Jvc3MgdGhlIHNhbXBsZXMgd2VyZSBmaWx0ZXJlZCBvdXQuCgpgYGB7cn0KZGltKGNkOF9leHApIC0gZGltKGNkOF9leHBfZmlsdGVyZWQpCgpgYGAKCjxicj4KSW50ZXJlc3RpbmdseSwgbWFueSBkdXBsaWNhdGUgZ2VuZXMgd2VyZSBhbHNvIGZpbHRlcmVkIG91dCBkdXJpbmcgdGhlIHByb2Nlc3MKYGBge3J9CiMgRGlkIHRoaXMgc29sdmUgdGhlIGR1cGxpY2F0ZSBpc3N1ZT8KCnN1bW1hcml6ZWRfZ2VuZV9jb3VudHNfZmlsdGVyZWQgPC0gc29ydCh0YWJsZShjZDhfZXhwX2ZpbHRlcmVkJGdlbmVTeW1ib2wpLGRlY3JlYXNpbmcgPSBUUlVFKQpgYGAKQmVmb3JlCmBgYHtyfQprYWJsZSh0KHN1bW1hcml6ZWRfZ2VuZV9jb3VudHNbd2hpY2goc3VtbWFyaXplZF9nZW5lX2NvdW50cz4xKVsxOjEwXV0pKQojIFlfUk5BICAgICAgIFUzICAgICAgc25vVTEzICAgTWV0YXpvYV9TUlAgICBTTk9SQTQwICAgICA3U0sgICAgICAgIFUxICAgICAgICAgIFU2ICAgICBTTk9SQTMxICAgICBTTk9SQTcwIAojIDE3NCAgICAgICAgIDE5ICAgICAgOSAgICAgICAgOCAgICAgICAgICAgICA3ICAgICAgICAgICA2ICAgICAgICAgIDQgICAgICAgICAgIDQgICAgICAzICAgICAgICAgICAzIApgYGAKQWZ0ZXIKYGBge3J9CiMgQWZ0ZXIKa2FibGUodChzdW1tYXJpemVkX2dlbmVfY291bnRzX2ZpbHRlcmVkW3doaWNoKHN1bW1hcml6ZWRfZ2VuZV9jb3VudHNfZmlsdGVyZWQ+MSlbMToxMF1dKSkKIyBZX1JOQSAgICAgVTMgICBTTk9SQTQwICAgN1NLICAgIENSSVAxICAgQ1JZQkczICAgR09MR0E3QiAgIElEUyAgIEtCVEJENCAgIEtJQUEwMzkxIAojIDI5ICAgICAgICA0ICAgIDMgICAgICAgICAyICAgICAgMiAgICAgICAyICAgICAgICAyICAgICAgICAgMiAgICAgMiAgICAgICAgMiAKCgoKIyBSZW1vdmluZyBEYXRhIGZvciBTYW5pdHkgU2FrZQpybSggbGlzdCA9IEZpbHRlciggZXhpc3RzLCBjKCJrZWVwIiwgInN1bW1hcml6ZWRfZ2VuZV9jb3VudHNfZmlsdGVyZWQiLCAiY3BtcyIsICJHU0U5NjU3OCIsICJzdW1tYXJpemVkX2dlbmVfY291bnRzIikgKSApCgoKYGBgCgoKIyMjIE5vcm1hbGl6YXRpb24gey50YWJzZXR9Cgo8YnI+Ck5vcm1hbGl6YXRpb24gaXMgYSBuZWNlc3Nhcnkgc3RlcCB0byBhZGp1c3QgdGhlIGRhdGEgc28gdGhhdCB3ZSBjYW4gZm9jdXMgbW9yZSBvbiBiaW9sb2dpY2FsIHZhcmlhdGlvbiB0aGFuIHRlY2huaWNhbCB2YXJpYXRpb24uCgoKQm94cGxvdCBvZiB0aGUgRmlsdGVyZWQgTWF0cml4IGFmdGVyIENQTSAmIGxvZzIgdHJhbnNmb3JtYXRpb24gKFByZS1Ob3JtYWxpemF0aW9uKQpgYGB7ciwgV2FybmluZyA9IEZBTFNFfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgTm9ybWFsaXphdGlvbiAtIEZpcnN0IHN0ZXAgaW4gQW5hbHlzaXMgLS0tLQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFdlIHdhbnQgdG8gbG9vayBhIGJpb2xvZ2ljYWwgdmFyaWF0aW9uIHJhdGhlciB0aGFuIHRlY2huaWNhbCB2YXJpYXRpb24KIyBPdXIgc2FtcGxpbmcgb2YgZGF0YSB3aWxsIGZvcm0gY2VydGFpbiBkaXN0cmlidXRpb24gbGlrZSBub3JtYWwsIGJpbW9kYWwsIHBvaXNzb24sIHBvd2VyIGxvZyAoYWxsIGFyZSB3ZWxsIGNoYXJhY3Rlcml6ZWQpCiMgb3Igc29tZSBvdGhlciBkaXN0cmlidXRpb25zCiMgaGVhZChjZDhfZXhwX2ZpbHRlcmVkWyw0OjE1XSkKIyBWaWV3KGNkOF9kYXRhMnBsb3QpCgojIEJveHBsb3Qgb2YgZWFjaCBvZiB0aGUgc2FtcGxlcwpjZDhfZGF0YTJwbG90IDwtIGxvZzIoY3BtKGNkOF9leHBfZmlsdGVyZWRbLDQ6MTVdKSkKYm94cGxvdChjZDhfZGF0YTJwbG90LCB4bGFiID0gIlNhbXBsZXMiLCB5bGFiID0gImxvZzIgQ1BNIiwgCiAgICAgICAgbGFzID0gMiwgY2V4ID0gMC41LCBjZXgubGFiID0gMC41LAogICAgICAgIGNleC5heGlzID0gMC41LCBtYWluID0gIkNEOCsgVCBQQk1DIFJOQVNlcSBTYW1wbGVzIikKCiMgQWRkaW5nIGEgbWVkaWFuIGxpbmUgYXQgZWFjaCBib3hwbG90IChtZWRpYW4gb2YgdGhlIG1lZGlhbnMgb2YgZWFjaCBzYW1wbGUpCmFibGluZShoID0gbWVkaWFuKGFwcGx5KGNkOF9kYXRhMnBsb3QsIDIsIG1lZGlhbikpLCBjb2wgPSAiZ3JlZW4iLCBsd2QgPSAwLjYsIGx0eSA9ICJkYXNoZWQiKQoKIyBUaGUgZGF0YSBJIGNob3NlIGhhcyBvdXRsaWVycyBpbiB0aGUgaGlnaGx5IGV4cHJlc3NlZCBnZW5lcyB3aGVyZWFzIG5vIG91dGxpZXJzIGluIHRoZSBsb3dseSBleHByZXNzZWQgZ2VuZXMKCiMjIyMjIyMjIyMjIyMjIFdoeSBkb2VzIG15IGRhdGEgbm90IGhhdmUgbmVnYXRpdmUgZXhwcmVzc2lvbiB2YWx1ZXM/ICMjIyMjIyMjIyMjIyMjIyMKCiMgTG9nMiB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgY3BtIG9mIHRoZSBuZXcgZmlsdGVyZWQgZXhwcmVzc2lvbiBkYXRhCgpjZDhfZXhwX2ZpbHRlcmVkX2NwbV9sb2cyIDwtIGxvZzIoY3BtKGNkOF9leHBfZmlsdGVyZWRbLDQ6MTVdKSkKYGBgCgpEZW5zaXR5IHBsb3Qgb2YgdGhlIEZpbHRlcmVkIE1hdHJpeCBhZnRlciBDUE0gJiBsb2cyIHRyYW5zZm9ybWF0aW9uCmBgYHtyfQoKIyBEaXN0cmlidXRpb24gb2Ygb3VyIERhdGEgLSBEZW5zaXR5IFBsb3QKCmNvdW50c19kZW5zaXR5IDwtIGFwcGx5KGNkOF9leHBfZmlsdGVyZWRfY3BtX2xvZzIsIE1BUkdJTiA9IDIsIGRlbnNpdHkpCiNjYWxjdWxhdGUgdGhlIGxpbWl0cyBhY3Jvc3MgYWxsIHRoZSBzYW1wbGVzCnhsaW0gPC0gMDsgeWxpbSA8LSAwCmZvciAoaSBpbiAxOmxlbmd0aChjb3VudHNfZGVuc2l0eSkpIHsKICB4bGltIDwtIHJhbmdlKGMoeGxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR4KSk7IAogIHlsaW0gPC0gcmFuZ2UoYyh5bGltLCBjb3VudHNfZGVuc2l0eVtbaV1dJHkpKQp9CmNvbHMgPC0gcmFpbmJvdyhsZW5ndGgoY291bnRzX2RlbnNpdHkpKQpsdHlzIDwtIHJlcCgxLCBsZW5ndGgoY291bnRzX2RlbnNpdHkpKQojcGxvdCB0aGUgZmlyc3QgZGVuc2l0eSBwbG90IHRvIGluaXRpYWxpemUgdGhlIHBsb3QKcGxvdChjb3VudHNfZGVuc2l0eVtbMV1dLCB4bGltPXhsaW0sIHlsaW09eWxpbSwgdHlwZT0ibiIsIAogICAgIHlsYWI9IlNtb290aGluZyBkZW5zaXR5IG9mIGxvZzItQ1BNIiwgbWFpbj0iIiwgY2V4LmxhYiA9IDAuODUpCiNwbG90IGVhY2ggbGluZQpmb3IgKGkgaW4gMTpsZW5ndGgoY291bnRzX2RlbnNpdHkpKSBsaW5lcyhjb3VudHNfZGVuc2l0eVtbaV1dLCBjb2w9Y29sc1tpXSwgbHR5PWx0eXNbaV0pCiNjcmVhdGUgbGVnZW5kCmxlZ2VuZCgidG9wcmlnaHQiLCBjb2xuYW1lcyhjZDhfZGF0YTJwbG90KSwgIAogICAgICAgY29sPWNvbHMsIGx0eT1sdHlzLCBjZXg9MC43NSwgCiAgICAgICBib3JkZXIgPSJibHVlIiwgIHRleHQuY29sID0gImdyZWVuNCIsIAogICAgICAgbWVyZ2UgPSBUUlVFLCBiZyA9ICJncmF5OTAiKQoKIyBSZW1vdmluZyBEYXRhIGZvciBzYW5pdHkgc2FrZQpybShpLCB4bGltLCB5bGltLCBjb2xzLCBsdHlzLCBjb3VudHNfZGVuc2l0eSkKCmBgYAo8YnI+Ck0gdnMgQSBQbG90IG9mIEN5Y2xlIDEgdnMgUHJlLVRyZWF0bWVudCBDRDheK14gVCBSTkEtc2VxCmBgYHtyLCBNZXNzYWdlID0gRkFMU0UscmVzdWx0cz0naGlkZSd9CgojIEltcGxlbWVudGluZyBUcmltbWVkIE1lYW4gb2YgTS1WYWx1ZXMgTm9ybWFsaXphdGlvbiAoVE1NKQoKIyBpbXBsZW1lbnRlZCBpbiBlZGdlUiBwYWNrYWdlLCBiYXNlZCBvbiBoeXBvdGhlc2lzIHRoYXQgbW9zdCBnZW5lcyBhcmUgbm90IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCwgc2FtcGxlLWJhc2VkCgojIGNvbG5hbWVzKGNkOF9leHBfZmlsdGVyZWRfY3BtX2xvZzIpCgojIE0gdnMgQSBwbG90CiMgT3JpZ2luYWxseSB1c2VkIGluIG1pY3JvYXJyYXkgd2l0aCB0d28gZHllIChyZWQgdnMgZ3JlZW4pIHRvIGFzc2F5IHRoZSB0ZWNobmljYWwgdmFyaWFiaWxpdHkgYmV0d2VlbiB0aGUgaW50ZW5zaXRpZXMKIyBvZiB0d28gZHllcwoKIyBNIC0gcmF0aW8sIGlzIHRoZSByYXRpbyBvZiBXZWVrIDMgb2YgQW50aS1QRC0xIFRoZXJhcHkgdnMgUHJlLVRyZWF0bWVudCwgYW5kIEEgaXMgdGhlIGF2ZXJhZ2Ugb2YgdGhlIHR3byBzYW1wbGVzCmxpbW1hOjpwbG90TUEobG9nMihjZDhfZXhwX2ZpbHRlcmVkX2NwbV9sb2cyWyxjKDIsMSldKSwgeWxhYj0iTSAtIHJhdGlvIGxvZyBleHByZXNzaW9uIiwgCiAgICAgICBtYWluPSJXZWVrIDMgb2YgQW50aS1QRC0xIFRoZXJhcHkgdnMgUHJldHJlYXRtZW50IikKYGBgClRoaXMgcGxvdCBpcyB0aGUgYmFzaXMgb2YgdHJpbW1lZCBtZWFuLCB3aGljaCBpcyB0aGUgYXZlcmFnZSBhZnRlciByZW1vdmluZyB1cHBlciBhbmQgbG93ZXIgcGVyY2VudGFnZSBvZiB0aGUgZGF0YSBwb2ludHMuCkFuZCB0aGF0IHBlcmNlbnRhZ2VzIGFyZSAzMCUgb2YgdGhlIE0gdmFsdWVzIGFuZCA1JSBvZiB0aGUgQSB2YWx1ZXMgYnkgZGVmYXVsdC4KPGJyPgo8YnI+CkZvcm1pbmcgREdFTGlzdCBhbmQgY2FsY05vcm1GYWN0b3JzKCkgdG8gZmluZCBhIHNldCBvZiBzY2FsaW5nIGZhY3RvcnMgZm9yIHRoZSBsaWJyYXJ5IHNpemVzIHRoYXQgbWluaW1pemUgdGhlIGxvZyBmb2xkCmNoYW5nZXMgYmV0d2VlbiB0aGUgc2FtcGxlcyBmb3IgbW9zdCBnZW5lcy4gVGhlIGRlZmF1bHQgbWV0aG9kIGZvciBjb21wdXRpbmcgdGhlc2Ugc2NhbGUgZmFjdG9ycyB1c2VzIGEgdHJpbW1lZCBtZWFuIG9mIE0tCnZhbHVlcyAoVE1NKSBiZXR3ZWVuIGVhY2ggcGFpciBvZiBzYW1wbGVzIFtAcm9iaW5zb24yMDEwc2NhbGluZ10KPGJyPgpUaGUgcHJvZHVjdCBvZiB0aGUgbGlicmFyeSBzaXplIGFuZCB0aGUgc2NhbGluZyBmYWN0b3IgaXMgY2FsbGVkIGVmZmVjdGl2ZSBsaWJyYXJ5IHNpemUsIHdoaWNoIHJlcGxhY2VzIHRoZSBvcmlnaW5hbCBsaWJyYXJ5CnNpemUgaW4gYWxsIGRvd25zdHJlYW0gYW5hbHlzaXMuCmBgYHtyfQojIFRyaW1tZWQgTWVhbiAtIGlzIHRoZSBhdmVyYWdlIGFmdGVyIHJlbW92aW5nIHRoZSB1cHBlciBhbmQgbG93ZXIgcGVyY2VudGFnZSBvZiB0aGUgZGF0YSBwb2ludHMgCiMgMzAlIG9mIHRoZSBNIHZhbHVlcyBhbmQgNSUgb2YgdGhlIEEgdmFsdWVzIGJ5IGRlZmF1bHQKCiMgQXBwbGljYXRpb24gb2YgVE1NIHRvIHRoZSBkYXRhc2V0IAoKIyBDcmVhdGluZyBhbiBlZGdlUiBjb250YWluZXIgZm9yIFJOQXNlcSBjb3VudCBkYXRhCmZpbHRlcmVkX2RhdGFfbWF0cml4IDwtIGFzLm1hdHJpeChjZDhfZXhwX2ZpbHRlcmVkWyw0OjE1XSkKcm93bmFtZXMoZmlsdGVyZWRfZGF0YV9tYXRyaXgpIDwtIGNkOF9leHBfZmlsdGVyZWQkaWQKCiMgY29sbmFtZXMoY2Q4X2V4cF9maWx0ZXJlZClbNDoxNV0KCiMgQ3JlYXRpbmcgREdFbGlzdCBvYmplY3QgZnJvbSB0aGUgZmlsdGVyZWQgZXhwcmVzc2lvbiBtYXRyaXgKIyBIZXJlLCBncm91cCBwYXJhbWV0ZXIgaXMgYSB2ZWN0b3IvZmFjdG9yIHRoYXQgZ2l2ZXMgdGhlIGV4cGVyaW1lbnRhbCBncm91cC9jb25kaXRpb24gZm9yIGVhY2ggc2FtcGxlL2xpYnJhcnkKIyBGb3IgdGhpcyBkYXRhc2V0LCBpdCBpcyB0aGUgZGlmZmVyZW50IGN5Y2xlcyBvZiBBbnRpLVBELTEgYW50aWJvZHkgdHJlYXRtZW50IHRvIHRoZSBtZWxhbm9tYSBwYXRpZW50cwpUcmVhdG1lbnRUeXBlIDwtIHNhbXBsZS5pbmZvLm1hdHJpeCRUcmVhdG1lbnQKbmFtZXMoVHJlYXRtZW50VHlwZSkgPC0gc2FtcGxlLmluZm8ubWF0cml4JFRpdGxlCiMgVHJlYXRtZW50VHlwZQogIApkR0VMaXN0LmZvci5UTU0gPC0gIERHRUxpc3QoY291bnRzPWZpbHRlcmVkX2RhdGFfbWF0cml4LCBncm91cD0gVHJlYXRtZW50VHlwZSkKCiMgUmVtb3ZpbmcgVHJlYXRtZW50VHlwZSwgZmlsdGVyZWRfZGF0YV9tYXRyaXgKCnJtKFRyZWF0bWVudFR5cGUsIGZpbHRlcmVkX2RhdGFfbWF0cml4KQoKIyBlZGdlUlVzZXJzR3VpZGUoKQojIFRoZSBjYWxjTm9ybUZhY3RvcnMgZnVuY3Rpb24gbm9ybWFsaXplcyBmb3IgUk5BIGNvbXBvc2l0aW9uIGJ5IGZpbmRpbmcgYSBzZXQgb2Ygc2NhbGluZwojIGZhY3RvcnMgZm9yIHRoZSBsaWJyYXJ5IHNpemVzIHRoYXQgbWluaW1pemUgdGhlIGxvZy1mb2xkIGNoYW5nZXMgYmV0d2VlbiB0aGUgc2FtcGxlcyBmb3IgbW9zdAojIGdlbmVzLiBUaGUgZGVmYXVsdCBtZXRob2QgZm9yIGNvbXB1dGluZyB0aGVzZSBzY2FsZSBmYWN0b3JzIHVzZXMgYSB0cmltbWVkIG1lYW4gb2YgTS0KIyAgIHZhbHVlcyAoVE1NKSBiZXR3ZWVuIGVhY2ggcGFpciBvZiBzYW1wbGVzIFszMF0KCiMgUm9iaW5zb24sIE0uRC4gYW5kIE9zaGxhY2ssIEEuICgyMDEwKS4gQSBzY2FsaW5nIG5vcm1hbGl6YXRpb24gbWV0aG9kIGZvcgojIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIG9mIFJOQS1zZXEgZGF0YS4gR2Vub21lIEJpb2xvZ3kgMTEsIFIyNS4KCiMgV2UgY2FsbCB0aGUgcHJvZHVjdCBvZiB0aGUgb3JpZ2luYWwgbGlicmFyeQojIHNpemUgYW5kIHRoZSBzY2FsaW5nIGZhY3RvciB0aGUgZWZmZWN0aXZlIGxpYnJhcnkgc2l6ZS4gVGhlIGVmZmVjdGl2ZSBsaWJyYXJ5IHNpemUgcmVwbGFjZXMgdGhlCiMgb3JpZ2luYWwgbGlicmFyeSBzaXplIGluIGFsbCBkb3duc3RlYW0gYW5hbHlzZXMuCgpkR0VMaXN0LmZvci5UTU0gPC0gIGNhbGNOb3JtRmFjdG9ycyhkR0VMaXN0LmZvci5UTU0pCiMgc3RyKGRHRUxpc3QuZm9yLlRNTSkKYGBgCgoqKlBsb3Qgb2YgdGhlIE5vcm1hbGl6ZWQgRGF0YSBiZWZvcmUgJiBhZnRlciBUTU0gbm9ybWFsaXphdGlvbioqCjxicj4KPGJyPgoqKlNpZGUgdG8gU2lkZSBCb3hwbG90IG9mIEJlZm9yZSAmIEFmdGVyIFRNTSoqCjxicj4KPGJyPgpUaGVyZSBpcyBhIGdyZWF0IGRpZmZlcmVuY2UgYmVmb3JlIGFuZCBhZnRlciB0aGUgbm9ybWFsaXphdGlvbi4gVGhlIGludGVycXVhcnRpbGUgcmFuZ2UgKGJldHdlZW4gUTEgYW5kIFEzKSBoYXMgbmFycm93ZWQgZG93biBhIGxvdC4KVGhlcmUgYXJlIGFsc28gbW9yZSBvdXRsaWVycyBpbiB0aGUgaGlnaGx5IGV4cHJlc3NlZCBnZW5lcyBpbiBhbGwgc2FtcGxlcy4gCmBgYHtyLCBXYXJuaW5nID0gRkFMU0V9CiMgR2V0dGluZyB0aGUgbm9ybWFsaXplZCBkYXRhCm5vcm1hbGl6ZWRfY291bnRzIDwtIGNwbShkR0VMaXN0LmZvci5UTU0sIGxvZyA9IFRSVUUpICMgV2hlbiBsb2cgaXMgVFJVRSwgaXQgcmV0dXJucyBsb2cyIHZhbHVlcy4KIyBTaWRlIHRvIFNpZGUgQm94cGxvdCBCZWZvcmUgYW5kIEFmdGVyIFRNTQoKcGFyKG1mcm93PWMoMSwyKSkKCmNkOF9kYXRhMnBsb3QgPC0gbG9nMihjcG0oY2Q4X2V4cF9maWx0ZXJlZFssNDoxNV0pKQpib3hwbG90KGNkOF9kYXRhMnBsb3QsIHhsYWIgPSAiU2FtcGxlcyIsIHlsYWIgPSAibG9nMiBDUE0iLCAKICAgICAgICBsYXMgPSAyLCBjZXggPSAwLjUsIGNleC5sYWIgPSAwLjUsCiAgICAgICAgY2V4LmF4aXMgPSAwLjUsIG1haW4gPSAiQ0Q4KyBUIFNhbXBsZXMiKQoKIyBBZGRpbmcgYSBtZWRpYW4gbGluZSBhdCBlYWNoIGJveHBsb3QgKG1lZGlhbiBvZiB0aGUgbWVkaWFucyBvZiBlYWNoIHNhbXBsZSkKYWJsaW5lKGggPSBtZWRpYW4oYXBwbHkoY2Q4X2RhdGEycGxvdCwgMiwgbWVkaWFuKSksIGNvbCA9ICJncmVlbiIsIGx3ZCA9IDAuNiwgbHR5ID0gImRhc2hlZCIpCgpkX2RhdGEycGxvdCA8LSBub3JtYWxpemVkX2NvdW50cwpib3hwbG90KGRfZGF0YTJwbG90LCB4bGFiID0gIlNhbXBsZXMiLCB5bGFiID0gImxvZzIgQ1BNIiwgCiAgICAgICAgbGFzID0gMiwgY2V4ID0gMC41LCBjZXgubGFiID0gMC41LAogICAgICAgIGNleC5heGlzID0gMC41LCBtYWluID0gIkNEOCsgVCBTYW1wbGVzIGFmdGVyIFRNTSIpCgojIEFkZGluZyBhIG1lZGlhbiBsaW5lIGF0IGVhY2ggYm94cGxvdCAobWVkaWFuIG9mIHRoZSBtZWRpYW5zIG9mIGVhY2ggc2FtcGxlKQphYmxpbmUoaCA9IG1lZGlhbihhcHBseShkX2RhdGEycGxvdCwgMiwgbWVkaWFuKSksIGNvbCA9ICJncmVlbiIsIGx3ZCA9IDAuNiwgbHR5ID0gImRhc2hlZCIpCgpwYXIobWZyb3c9YygxLDEpKQoKIyBSZW1vdmluZyBEYXRhCnJtKCBkX2RhdGEycGxvdCkKYGBgCgoqKlNpZGUgdG8gU2lkZSBEZW5zaXR5IFBsb3QgLSBCZWZvcmUgKGxlZnQpICYgQWZ0ZXIgKHJpZ2h0KSBOb3JtYWxpemF0aW9uKioKPGJyPgo8YnI+ClRoZSB0d28gZGVuc2l0eSBwbG90cyBhbHNvIHNob3cgZ3JlYXQgZGlmZmVyZW5jZXMuIFRoZSBsb2cyLWNwbSB0cmFuc2Zvcm1lZCBnZW5lIGNvdW50cyBpbiA1IHJhbmdlIGhhdmUgZGVjcmVhc2VkIGEgbG90IApjb21wYXJlZCB0byB0aGUgb3JpZ2luYWwgcHJlLW5vcm1hbGl6YXRpb24gc2FtcGxlLgpgYGB7cn0KcGFyKG1mcm93ID0gYygxLDIpKQojIERpc3RyaWJ1dGlvbiBvZiBvdXIgRGF0YSAtIERlbnNpdHkgUGxvdAoKY291bnRzX2RlbnNpdHkgPC0gYXBwbHkoY2Q4X2V4cF9maWx0ZXJlZF9jcG1fbG9nMiwgTUFSR0lOID0gMiwgZGVuc2l0eSkKI2NhbGN1bGF0ZSB0aGUgbGltaXRzIGFjcm9zcyBhbGwgdGhlIHNhbXBsZXMKeGxpbSA8LSAwOyB5bGltIDwtIDAKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgewogIHhsaW0gPC0gcmFuZ2UoYyh4bGltLCBjb3VudHNfZGVuc2l0eVtbaV1dJHgpKTsgCiAgeWxpbSA8LSByYW5nZShjKHlsaW0sIGNvdW50c19kZW5zaXR5W1tpXV0keSkpCn0KY29scyA8LSByYWluYm93KGxlbmd0aChjb3VudHNfZGVuc2l0eSkpCmx0eXMgPC0gcmVwKDEsIGxlbmd0aChjb3VudHNfZGVuc2l0eSkpCiNwbG90IHRoZSBmaXJzdCBkZW5zaXR5IHBsb3QgdG8gaW5pdGlhbGl6ZSB0aGUgcGxvdApwbG90KGNvdW50c19kZW5zaXR5W1sxXV0sIHhsaW09eGxpbSwgeWxpbT15bGltLCB0eXBlPSJuIiwgCiAgICAgeWxhYj0iU21vb3RoaW5nIGRlbnNpdHkgb2YgbG9nMi1DUE0iLCBtYWluPSIiLCBjZXgubGFiID0gMC44NSkKI3Bsb3QgZWFjaCBsaW5lCmZvciAoaSBpbiAxOmxlbmd0aChjb3VudHNfZGVuc2l0eSkpIGxpbmVzKGNvdW50c19kZW5zaXR5W1tpXV0sIGNvbD1jb2xzW2ldLCBsdHk9bHR5c1tpXSkKI2NyZWF0ZSBsZWdlbmQKbGVnZW5kKCJ0b3ByaWdodCIsIGNvbG5hbWVzKGNkOF9kYXRhMnBsb3QpLCAgCiAgICAgICBjb2w9Y29scywgbHR5PWx0eXMsIGNleD0wLjc1LCAKICAgICAgIGJvcmRlciA9ImJsdWUiLCAgdGV4dC5jb2wgPSAiZ3JlZW40IiwgCiAgICAgICBtZXJnZSA9IFRSVUUsIGJnID0gImdyYXk5MCIpCgojIFJlbW92aW5nIERhdGEgZm9yIHNhbml0eSBzYWtlCnJtKGksIHhsaW0sIHlsaW0sIGNvbHMsIGx0eXMsIGNvdW50c19kZW5zaXR5KQoKIyBBZnRlciBOb3JtYWxpemF0aW9uIC0tLS0KCgoKIyBHZXR0aW5nIGRpc3RyaWJ1dGlvbiBncmFwaCBmb3Igbm9ybWFsaXplZCBkYXRhCmNvdW50c19kZW5zaXR5IDwtIGFwcGx5KG5vcm1hbGl6ZWRfY291bnRzLCBNQVJHSU4gPSAyLCBkZW5zaXR5KQojY2FsY3VsYXRlIHRoZSBsaW1pdHMgYWNyb3NzIGFsbCB0aGUgc2FtcGxlcwp4bGltIDwtIDA7IHlsaW0gPC0gMApmb3IgKGkgaW4gMTpsZW5ndGgoY291bnRzX2RlbnNpdHkpKSB7CiAgeGxpbSA8LSByYW5nZShjKHhsaW0sIGNvdW50c19kZW5zaXR5W1tpXV0keCkpOyAKICB5bGltIDwtIHJhbmdlKGMoeWxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR5KSkKfQpjb2xzIDwtIHJhaW5ib3cobGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKbHR5cyA8LSByZXAoMSwgbGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKI3Bsb3QgdGhlIGZpcnN0IGRlbnNpdHkgcGxvdCB0byBpbml0aWFsaXplIHRoZSBwbG90CnBsb3QoY291bnRzX2RlbnNpdHlbWzFdXSwgeGxpbT14bGltLCB5bGltPXlsaW0sIHR5cGU9Im4iLCAKICAgICB5bGFiPSJTbW9vdGhpbmcgZGVuc2l0eSBvZiBsb2cyLUNQTSIsIG1haW49IiIsIGNleC5sYWIgPSAwLjg1KQojcGxvdCBlYWNoIGxpbmUKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgbGluZXMoY291bnRzX2RlbnNpdHlbW2ldXSwgY29sPWNvbHNbaV0sIGx0eT1sdHlzW2ldKQojY3JlYXRlIGxlZ2VuZApsZWdlbmQoInRvcHJpZ2h0Iiwgc2FtcGxlLmluZm8ubWF0cml4JExhYmVsLCAgCiAgICAgICBjb2w9Y29scywgbHR5PWx0eXMsIGNleD0wLjc1LCAKICAgICAgIGJvcmRlciA9ImJsdWUiLCAgdGV4dC5jb2wgPSAiZ3JlZW40IiwgCiAgICAgICBtZXJnZSA9IFRSVUUsIGJnID0gImdyYXk5MCIpCgojIFJlbW92aW5nIERhdGEgZm9yIFNhbml0eSBTYWtlCnJtKGNvdW50c19kZW5zaXR5LCBjb2xzLCBsdHlzLCB4bGltLCB5bGltLCBpLCBjZDhfZGF0YTJwbG90KQpwYXIobWZyb3cgPSBjKDEsMSkpCmBgYAoqKlBsb3Qgb2YgTWVhbiAtIFZhcmlhbmNlIGFmdGVyIE5vcm1hbGl6YXRpb24qKgo8YnI+Cjxicj4KVGhpcyBwbG90IHNob3dzIHVzIGhvdyB0aGUgZGlmZmVyZW50IGRpc3BlcnNpb24gdmFsdWVzIHdlIGhhdmUgY2FsY3VsYXRlZCBpbmZsdWVuY2UgdGhlIGRhdGEuCjxicj4KVGhlIHJhdyB2YXJpYW5jZXMgb2YgdGhlIGNvdW50cyBhcmUgdGhlIGdyYXkgZG90cwo8YnI+ClZhcmlhbmNlID0gbWVhbiAoYXNzdW1wdGlvbiBvZiBwb2lzc29uIGRpc3RyaWJ1dGlvbikgaXMgdGhlIHNvbGlkIGJsYWNrIGxpbmUuCjxicj4KVmFyaWFuY2VzIGVzdGltYXRlZCB1c2luZyB0aGUgdGFnd2lzZSBkaXNwZXJzaW9ucyBhcmUgYmx1ZSBkb3RzLgo8YnI+ClZhcmlhbmNlcyBlc3RpbWF0ZWQgdXNpbmcgdGhlIGNvbW1vbiBkaXNwZXJzaW9ucyBhcmUgdGhlIHNvbGlkIGJsdWUgbGluZXMuCjxicj4KPGJyPgpCaW5uZWQgQ29tbW9uIERpc3BsYXkgVmFyaWFuY2UgPSBSZWQgWAo8YnI+CkNvbW1vbiBEaXNwZXJzaW9uIGZvciBlYWNoIGJpbiBvZiBnZW5lcyBhbmQgc2hvdyB0aGUgdmFyaWFuY2VzIGNvbXB1dGVkIGZyb20gdGhvc2UgYmlubmVkIGNvbW1vbiBkaXNwZXJzaW9ucyBhbmQgdGhlIG1lYW4gZXhwcmVzc2lvbiAKbGV2ZWwgb2YgdGhlIHJlc3BlY3RpdmUgYmluIG9mIGdlbmVzLgo8YnI+CkJsdWUgbGluZSBzaG93cyB0aGUgbWVhbi12YXJpYW5jZSByZWxhdGlvbnNoaXAgZm9yIGEgTmVnYXRpdmUgQmlub21pYWwgbW9kZWwgd2l0aCBjb21tb24gZGlzcGVyc2lvbi4KYGBge3J9Cm1vZGVsX2Rlc2lnbiA8LSBtb2RlbC5tYXRyaXgofnNhbXBsZS5pbmZvLm1hdHJpeCRQYXRpZW50ICsgc2FtcGxlLmluZm8ubWF0cml4JFRyZWF0bWVudCAgKyAwKQpkR0VMaXN0LmZvci5UTU0gPC0gZXN0aW1hdGVEaXNwKGRHRUxpc3QuZm9yLlRNTSwgbW9kZWxfZGVzaWduKQoKcGxvdE1lYW5WYXIoZEdFTGlzdC5mb3IuVE1NLCBzaG93LnJhdy52YXJzID0gVFJVRSwgc2hvdy50YWd3aXNlLnZhcnM9VFJVRSwgCiAgICAgICAgICAgIHNob3cuYXZlLnJhdy52YXJzID0gVFJVRSwgIAogICAgICAgICAgICBOQmxpbmU9VFJVRSwKICAgICAgICAgICAgc2hvdy5iaW5uZWQuY29tbW9uLmRpc3AudmFycyA9IFRSVUUpCgojIFJlbW92aW5nIG1vZGVsX2Rlc2lnbiBmb3IgU2FuaXR5IFNha2UKcm0obW9kZWxfZGVzaWduKQpgYGAKSW4gYSBSTkEgc2VxIGV4cGVyaW1lbnQsIHdlIG1hcCB0aGUgc2VxdWVuY2luZyByZWFkcyB0byB0aGUgcmVmZXJlbmNlIGdlbm9tZSBhbmQgY291bnQgaG93IG1hbnkgcmVhZHMgZmFsbCB3aXRoaW4gYSBnaXZlbiBnZW5lIChvciBleG9uKS4KPGJyPgpJbiBvdGhlciB3b3JkcywgdGhlIGlucHV0cyBmb3Igc3RhdGlzdGljYWwgYW5hbHlzaXMgYXJlIGRpc2NyZXRlIG5vbi1uZWdhdGl2ZSBpbnRlZ2VycyBvciBjb3VudHMgZm9yIGVhY2ggZ2VuZSBpbiBlYWNoIHNhbXBsZS4KPGJyPgo8YnI+ClRoZSB0b3RhbCBudW1iZXIgb2YgcmVhZHMgZm9yIGVhY2ggc2FtcGxlIHRlbmRzIHRvIGJlIGluIG1pbGxpb25zIHdoaWxlIHRoZSBjb3VudHMgcGVyIGdlbmUgdmFyeSBjb25zaWRlcmFibHkgYnV0IHRlbmQgdG8gYmUgaW4gdGVucywKaHVuZHJlZHMsIG9yIHRob3VzYW5kcy4gCjxicj4KPGJyPgpUaGVyZWZvcmUsIHRoZSBjaGFuY2Ugb2YgYSBnaXZlbiByZWFkIHRvIGJlIG1hcHBlZCB0byBhbnkgc3BlY2lmaWMgZ2VuZSBpcyByYXRoZXIgc21hbGwuIAo8YnI+ClBvaXNzb24gcHJvY2VzcyBpcyB3aGVuIGRpc2NyZXRlIGV2ZW50cyBhcmUgc2FtcGxlZCBvdXQgb2YgYSBsYXJnZSBwb29sIHdpdGggbG93IHByb2JhYmlsaXR5LCBhbmQgZWFybGllciBpdGVyYXRpb25zIG9mIFJOQS1zZXEgYW5hbHlzaXMKbW9kZWxlZCBzZXF1ZW5jaW5nIGRhdGEgYXMgYSBQb2lzc29uIGRpc3RyaWJ1dGlvbi4KPGJyPgpPbmUgcHJvYmxlbSB3aXRoIFBvaXNzb24gZGlzdHJpYnV0aW9uIGlzIHRoYXQgdmFyaWFiaWxpdHkgb2YgcmVhZCBjb3VudHMgaW4gc2VxdWVuY2luZyBleHBlcmltZW50cyBpcyBncmVhdGVyIHRoYW4gdGhlIHZhcmlhbmNlIApQb2lzc29uIGRpc3RyaWJ1dGlvbiBhbGxvd3MsIHdoaWNoIGFzc3VtZXMgaXRzIHZhcmlhbmNlIGlzIGVxdWFsIHRvIHRoZSBtZWFuLgo8YnI+Cjxicj4KVGhlIG5lZ2F0aXZlIGJpbm9taWFsIChOQikgZGlzdHJpYnV0aW9uLCB3aGljaCBpcyB1c2VkIGluc3RlYWQsIGNhbiBiZSBkZXNjcmliZWQgYXMgUG9pc3Nvbi1HYW1tYSBtaXh0dXJlIGRpc3RyaWJ1dGlvbiwgd2hpY2ggYWxsb3dzCnRoZSBleHRyYSB2YXJpYW5jZSBieSBpbmNsdWRpbmcgdGhlIHJhdGUgcGFyYW1ldGVyIGdhbW1hLgo8YnI+PGJyPgpBbGwgb2YgdGhlIGFib3ZlIGludGVycHJldGF0aW9uIHdhcyB0YWtlbiBmcm9tIHRoZSBmb2xsb3dpbmcgc291cmNlLCB3aGljaCBoZWxwZWQgbWUgdW5kZXJzdGFuZCBob3cgc3RhdGlzdGljaWFucyBtb2RlbGVkIHRoaXMgcmVhZHMgdG8KY291bnRzIGV2ZW50IFtAbGlwcF8yMDE2XSEKCiMjIyBIYW5kbGluZyBCaW9sb2dpY2FsIFJlcGxpY2F0ZXMgey50YWJzZXR9CgpCaW9sb2dpY2FsIHJlcGxpY2F0ZXMgYXJlIHRoZSBzYW1lIGV4cGVyaW1lbnRzIHBlcmZvcm1lZCBvbiBtdWx0aXBsZSBzYW1wbGVzIHRoYXQgYXJlIG9mIHNhbWUgdHlwZSBvZiBjZWxscy90aXNzdWVzLiAKPGJyPgpUaGlzIGlzIGRpZmZlcmVudCBmcm9tIHRlY2huaWNhbCByZXBsaWNhdGVzLCB3aGljaCBhcmUgc2FtZSBleHBlcmltZW50cyBwZXJmb3JtZWQgb24gc2luZ2xlIHNhbXBsZSBtdWx0aXBsZSB0aW1lcy4KPGJyPgpGb3IgbXkgZGF0YXNldCwgdGhlIDQgZ3JvdXBzIG9mIGJpb2xvZ2ljYWwgcmVwbGljYXRlcyBhcmUgUHJlLXRyZWF0bWVudCwgQ3ljbGUgMSwgQ3ljbGUgMywgQ3ljbGUgNCBzYW1wbGVzLiBFYWNoIGdyb3VwIGhhcyAzIGJpb2xvZ2ljYWwgcmVwbGljYXRlcywgZnJvbSAzIGRpZmZlcmVudCBwYXRpZW50cwo8YnI+Cjxicj4KV2UgY2FuIHZpc3VhbGl6ZSB0aGUgY2x1c3RlcmluZyBvZiB0aGUgcmVwbGljYXRlcyBieSBNdWx0aWRpbWVuc2lvbmFsIFNjYWxpbmcgZ3JhcGguCgpgYGB7cn0KIyBNdWx0aWRpbWVuc2lvbmFsIFNjYWxpbmcgUGxvdHMgYmV0d2VlbiBTYW1wbGVzCnBsb3RNRFMoZEdFTGlzdC5mb3IuVE1NLCBsYWJlbHM9c2FtcGxlLmluZm8ubWF0cml4JExhYmVsLAogICAgICAgIGNvbCA9IGMoImRhcmtncmVlbiIsImJsdWUiLCJjeWFuIiwgImdyZWVuIilbZmFjdG9yKHNhbXBsZS5pbmZvLm1hdHJpeCRQYXRpZW50KV0pCmBgYApUaGUgc2FtZSBwYXRpZW50IHNhbXBsZXMgY2x1c3RlcmVkIGNsb3NlbHkgdG9nZXRoZXIgYWxvbmcgeC1heGlzLiBXaXRoaW4gdGhlIHNhbWUgcGF0aWVudCBzYW1wbGVzLCB0aGVyZSB3ZXJlIHZhcmlhdGlvbnMgb2YgdGhlIHNhbXBsZXMgYWxvbmcgdGhlIHktYXhpcywgZGVwZW5kaW5nIG9uIHRoZSB0cmVhdG1lbnQuCkludGVyZXN0aW5nLCB3aGlsZSB0cmVhdG1lbnQgY3ljbGUgMSBzYW1wbGVzIHdlcmUgdGhlIG91dGxpZXJzIGZvciBwYXRpZW50IEEgJiBCLCB0cmVhdG1lbnQgY3ljbGUgMyBzYW1wbGUgd2FzIHRoZSBvdXRsaWVyIGZvciBwYXRpZW50IEMuCgo8YnI+PGJyPgoqKlBsb3Qgb2YgTWVhbiBWYXJpYW5jZSoqCjxicj48YnI+ClNhbWUgcGxvdCBpbiB0aGUgTm9ybWFsaXphdGlvbiBUYWIKYGBge3J9Cm1vZGVsX2Rlc2lnbiA8LSBtb2RlbC5tYXRyaXgofnNhbXBsZS5pbmZvLm1hdHJpeCRQYXRpZW50ICsgc2FtcGxlLmluZm8ubWF0cml4JFRyZWF0bWVudCAgKyAwKQpkR0VMaXN0LmZvci5UTU0gPC0gZXN0aW1hdGVEaXNwKGRHRUxpc3QuZm9yLlRNTSwgbW9kZWxfZGVzaWduKQoKcGxvdE1lYW5WYXIoZEdFTGlzdC5mb3IuVE1NLCBzaG93LnJhdy52YXJzID0gVFJVRSwgc2hvdy50YWd3aXNlLnZhcnM9VFJVRSwgCiAgICAgICAgICAgIHNob3cuYXZlLnJhdy52YXJzID0gVFJVRSwgIAogICAgICAgICAgICBOQmxpbmU9VFJVRSwKICAgICAgICAgICAgc2hvdy5iaW5uZWQuY29tbW9uLmRpc3AudmFycyA9IFRSVUUpCgojIFJlbW92aW5nIG1vZGVsX2Rlc2lnbiBmb3IgU2FuaXR5IFNha2UKcm0obW9kZWxfZGVzaWduKQpgYGAKCkFjY29yZGluZyB0bywgZWRnZVIsIGRpc3BlcnNpb24gc3F1YXJlZCBpcyBiaW9sb2dpY2FsIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbiAoQkNWKSBzbyBkaXNwZXJzaW9uIGlzIGEgbWVhc3VyZSBvZiBob3cgCm11Y2ggdmFyaWF0aW9uIHRoZXJlIGlzIGluIHRoZSBzYW1wbGVzLgpUaGUgcmF3IHZhcmlhbmNlcyBvZiB0aGUgY291bnRzIGFyZSB0aGUgZ3JheSBkb3RzCjxicj48YnI+ClZhcmlhbmNlID0gbWVhbiAoYXNzdW1wdGlvbiBvZiBwb2lzc29uIGRpc3RyaWJ1dGlvbikgaXMgdGhlIHNvbGlkIGJsYWNrIGxpbmUuCjxicj4KVmFyaWFuY2VzIGVzdGltYXRlZCB1c2luZyB0aGUgdGFnd2lzZSBkaXNwZXJzaW9ucyBhcmUgYmx1ZSBkb3RzLgo8YnI+ClZhcmlhbmNlcyBlc3RpbWF0ZWQgdXNpbmcgdGhlIGNvbW1vbiBkaXNwZXJzaW9ucyBhcmUgdGhlIHNvbGlkIGJsdWUgbGluZXMuCjxicj48YnI+Ck15IHNhbXBsZXMgc2VlbSB0byBmaXQgd2VsbCB3aXRoIHRoZSBOQiBkaXN0cmlidXRpb24gaW4gdGVybXMgb2YgbWVhbi12YXJpYW5jZS4KPGJyPjxicj4KKipJIGhhdmUgZGVjaWRlZCB0byBrZWVwIHRoZXNlIGJpb2xvZ2ljYWwgcmVwbGljYXRlcyBvZiBDeWNsZSAxLCAzLCA0LCBhbmQgUHJlLXRyZWF0bWVudCBmb3IgbXkgZG93bnN0cmVhbSBhbmFseXNpcy4qKgoKCiMjIAoKIyMgRXhwcmVzc2lvbiBWYWx1ZXMgey50YWJzZXR9CgojIyMgSWRlbnRpZmVyIE1hcHBpbmcKClRoZSBkYXRhIGp1c3QgZG9lc24ndCBjb250YWluIHRoZSBpZGVudGlmZXJzIHRoYXQgd2UncmUgaW50ZXJlc3RlZCBpbiAtIGkuZSBnZW5lcy4gVGVjaG5vbG9neSBpdHNlbGYgd29ya3Mgb24gYSBkaWZmZXJlbnQgbGV2ZWwgYW5kIHRyYWNrcyBkaWZmZXJlbnQgaW5mb3JtYXRpb24gc28gb2Z0ZW4KYXJlbid0IHdvcmtpbmcgZ2VuZSBsZXZlbCBkYXRhIC0gbGlrZSBmb3IgUk5BLXNlcSwgaXQgZGVhbHMgd2l0aCByZWFkIGNvdW50cyBvZiBzaG9ydCBmcmFnbWVudHMgb2YgUk5BIHRoYXQgZG9uJ3QgbmVjZXNzYXJpbHkgbWFwIHRvIGFuIGluZGl2aWR1YWwgZ2VuZS4KCkluIG90aGVyIHdvcmRzLCB0aGUgc2hvcnQgZnJhZ21lbnRzIG9mIFJOQSBtYXkgbm90IHJlcHJlc2VudCAoaS5lLiBtYXAgdG8pIGEgZ2VuZS4KPGJyPgo8YnI+ClRoZSBwZXJrcyBvZiBSTkEgc2VxLCB0aG91Z2gsIGlzIHRoYXQgaXQgY2FuIGJlIHJlLWFuYWx5emVkIHRvIGdpdmUgbmV3IGluZm9ybWF0aW9uIHRvIHVuY292ZXIgbmV3IHRoaW5ncywgYXMgbmV3IGdlbmVzICYgcmVndWxhdG9yeSBtZWNoYW5pc21zIGFyZSBiZWluZyBkaXNjb3ZlcmVkLgo8YnI+Cjxicj4KQ29ubmVjdGluZyB0byBoZzE5IChHUkNoMzcpIGh1bWFuIGdlbmUgZW5zZW1ibCBpbiBvcmRlciB0byBnZXQgdGhlIEhHTkMgc3ltYm9scyAmIFVzaW5nIGdldEJNKCkgZnVuY3Rpb24gdG8gcmV0cmlldmUgdGhlIGF0dHJpYnV0ZXMgLSBFbnNlbWJsIGdlbmUgaWRzIGFuZCBIR05DIHN5bWJvbHMgLSB0aGF0IG1hdGNoZXMgdGhlIEVuc2VtYmwgZ2VuZSBpZHMgaW4gbXkgZGF0YXNldC4KPGJyPgpoZzE5IGJlY2F1c2UgdGhlIHJlYWRzIHdlcmUgYWxpZ25lZCB1c2luZyBoZzE5IHJlZmVyZW5jZSBnZW5vbWUgKHN0YXRlZCBpbiB0aGUgZGF0YSBwcm9jZXNzaW5nIHByb3RvY29sIHNlY3Rpb24pLgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CmVuc2VtYmxfZ3IzNyA8LSB1c2VNYXJ0KGJpb21hcnQgPSAiZW5zZW1ibCIsIGRhdGFzZXQgPSAiaHNhcGllbnNfZ2VuZV9lbnNlbWJsIiwgIGhvc3Q9ImdyY2gzNy5lbnNlbWJsLm9yZyIpCmNkOF9leHBfZmlsdGVyZWQkaWQgIDwtIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiLCB4ID0gY2Q4X2V4cF9maWx0ZXJlZCRpZCwgaWdub3JlLmNhc2UgPSBUUlVFKQoKIyBoZWFkKGNkOF9leHBfZmlsdGVyZWQpCgojIE5vdyBEb2luZyB0aGUgSWRlbnRpZmllciBNYXBwaW5nCgpjb252ZXJzaW9uX3N0YXNoIDwtICJjZDhfaWRfY29udmVyc2lvbi5yZHMiCmlmKGZpbGUuZXhpc3RzKGNvbnZlcnNpb25fc3Rhc2gpKXsKICBjZDhfaWRfY29udmVyc2lvbiA8LSByZWFkUkRTKGNvbnZlcnNpb25fc3Rhc2gpCn0gZWxzZSB7CiAgY2Q4X2lkX2NvbnZlcnNpb24gPC0gZ2V0Qk0oYXR0cmlidXRlcyA9IGMoImVuc2VtYmxfZ2VuZV9pZCIsImhnbmNfc3ltYm9sIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJzID0gYygiZW5zZW1ibF9nZW5lX2lkIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBmYWN0b3IoY2Q4X2V4cF9maWx0ZXJlZCRpZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJ0ID0gZW5zZW1ibF9ncjM3KQogIHNhdmVSRFMoY2Q4X2lkX2NvbnZlcnNpb24sIGNvbnZlcnNpb25fc3Rhc2gpCn0KYGBgCgpQcm9iaW5nIG15IG5ldyByZXRyaWV2ZWQgbWFwcGluZyB3aXRoIGhlYWQoKQpgYGB7cn0KaGVhZChjZDhfaWRfY29udmVyc2lvbikKCmBgYAoKVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbnVtYmVyIG9mIG1hcHBpbmdzIHRoYXQgYXJlIG5vdCBtaXNzaW5nIHZhbHVlcyBvciBlbXB0eSBzdHJpbmdzIGFuZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIG5vcm1hbGl6ZWQgc2V0IC0KVGhpcyBkb2Vzbid0IG5lY2Vzc2FyaWx5IG1lYW4gd2UgYXJlIG1pc3Npbmcgb25seSB0aGF0IG1hbnkKPGJyPjxicj4KCmBgYHtyfQojIEdldHRpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbnVtYmVyIG9mIG1hcHBpbmdzIGFuZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIG5vcm1hbGl6ZWQgc2V0CiMgQlVUIHRoaXMgZG9lc24ndCBuZWNlc3NhcmlseSBtZWFuIHdlIGFyZSBtaXNzaW5nIG9ubHkgdGhhdCBtYW55Cgpucm93KG5vcm1hbGl6ZWRfY291bnRzKSAtIChzdW0oIWlzLm5hKGNkOF9pZF9jb252ZXJzaW9uJGhnbmNfc3ltYm9sKSkgLSBzdW0obmNoYXIoY2Q4X2lkX2NvbnZlcnNpb24kaGduY19zeW1ib2wpID09IDApKQpgYGAKTWVyZ2luZyB0aGUgbm9ybWFsaXplZF9jb3VudHMgbWF0cml4IHRvIHRoZSBuZXdseSBtYXBwZWQgaWRlbmZpZXJzIAomIGhlYWQoKSB0byBnZXQgdGhlIG1lcmdlZCBub3JtYWxpemVkX2NvdW50c19hbm5vdCBtYXRyaXggaXRzIGZpcnN0IGxvb2sKYGBge3J9CiMgTWVyZ2luZyB0aGUgbmV3IGlkZW50aWZlcnMKCiMgaGVhZChyb3duYW1lcyhub3JtYWxpemVkX2NvdW50cykpCnJvd25hbWVzKG5vcm1hbGl6ZWRfY291bnRzKSA8LSBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIiwgeCA9IHJvd25hbWVzKG5vcm1hbGl6ZWRfY291bnRzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBUUlVFKQojIGhlYWQocm93bmFtZXMobm9ybWFsaXplZF9jb3VudHMpKQoKIyBhbGwueSA9IFRSVUU7IHJpZ2h0IG91dGVyIGpvaW4gd2hlcmUgdGhlIG5vcm1hbGl6ZWRfY291bnRzIGlzIHByZXNlcnZlZAojIGJ5LnggPSAxIHJlZmVycyB0byB0aGUgZW5zZW1ibF9nZW5lX2lkIGNvbHVtbiBvZiBjZDhfaWRfY29udmVyc2lvbiwgYW5kIGJ5LnkgPSAwIHJlZmVycyB0byB0aGUgcm93IG5hbWVzIG9mIHRoZQojIG5vcm1hbGl6ZWRfY291bnRzCgpub3JtYWxpemVkX2NvdW50c19hbm5vdCA8LSBtZXJnZSh4ID0gY2Q4X2lkX2NvbnZlcnNpb24sIHkgPSBub3JtYWxpemVkX2NvdW50cyxieS54ID0gMSwgYnkueSA9IDAsIGFsbC55PVRSVUUpCgoKIyBUd28gbW9yZSBhZGRpdGlvbmFsIGNvbHVtbnM6IGVuc2VtYmxfZ2VuZV9pZCAmIGhnbmNfc3ltYm9sCgpoZWFkKG5vcm1hbGl6ZWRfY291bnRzX2Fubm90KVssMTo2XQogICAKCnJtKCBjdXJyZW50X2dwbF9pbmZvKQpgYGAKCgoKCiMjIyBFeHByZXNzaW9uIHZhbHVlcyBoYXZpbmcgZGlmZmVyZW50IGVuc2VtYmwgZ2VuZSBpZHMgYnV0IG1hcCB0byBzYW1lIEhVR08gc3ltYm9scyBPUiBub3QgbWFwcGluZyB0byBjdXJyZW50IEhVR08gc3ltYm9sc3sudGFic2V0fQoKVG8gZGV0ZXJtaW5lIHRoZSBleHByZXNzaW9uIHZhbHVlcyB0aGF0IGhhdmUgZGlmZmVyZW50IGVuc2VtYmwgZ2VuZSBpZHMgYnV0IG1hcCB0byBzYW1lIEhVR08gc3ltYm9scywgCkkgbmVlZGVkIHRvIGNoZWNrIHdoZXRoZXIgdGhlcmUgd2VyZSByb3dzIHdpdGggc2FtZSBIVUdPIHN5bWJvbHMgYnV0IHdpdGggZGlmZmVyZW50IGVuc2VtYmwgZ2VuZSBpZHMgaW4gCnRoZSBtZXJnZWQgbm9ybWFsaXplZF9jb3VudF9hbm5vdCBtYXRyaXguCjxicj48YnI+ClRvIGNoZWNrIGZvciBzYW1lIEhVR08gc3ltYm9scywgSSBmaXJzdCBjaGVja2VkIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHRvdGFsIGxlbmd0aCBvZiB0aGUgCkhVR08gc3ltYm9scyB2cyBsZW5ndGggb2YgdGhlIHVuaXF1ZSBIVUdPIHN5bWJvbHMKPGJyPjxicj4KVG90YWwgTGVuZ3RoIG9mIEhVR08gU3ltYm9scyBpbiB0aGUgbWVyZ2VkIGRhdGFzZXQKYGBge3J9Cmxlbmd0aChub3JtYWxpemVkX2NvdW50c19hbm5vdCRoZ25jX3N5bWJvbCkKIyBbMV0gMTcxMjAKYGBgCkxlbmd0aCBvZiBVbmlxdWUgSFVHTyBTeW1ib2xzIGluIHRoZSBtZXJnZWQgZGF0YXNldApgYGB7cn0KbGVuZ3RoKHVuaXF1ZShub3JtYWxpemVkX2NvdW50c19hbm5vdCRoZ25jX3N5bWJvbCkpCiMgWzFdIDE0NDExCmBgYApEaWZmZXJlbmNlIGJldHdlZW4gdGhlIHRvdGFsIGxlbmd0aCBvZiB0aGUgSFVHTyBzeW1ib2xzIHZzIGxlbmd0aCBvZiB0aGUgdW5pcXVlIEhVR08gc3ltYm9scwo8YnI+CmkuZS4gVGhlIG51bWJlciBvZiBkdXBsaWNhdGVkIEhVR08gc3ltYm9scwpgYGB7cn0KbGVuZ3RoKG5vcm1hbGl6ZWRfY291bnRzX2Fubm90JGhnbmNfc3ltYm9sKSAtIGxlbmd0aCh1bmlxdWUobm9ybWFsaXplZF9jb3VudHNfYW5ub3QkaGduY19zeW1ib2wpKSAKIyBbMV0gMjcwOQpgYGAKSSB0aGVuIHRvb2sgYSBnbGFuY2UgYXQgdGhlIGR1cGxpY2F0ZWQgSFVHTyBzeW1ib2xzIGRhdGEuZnJhbWUgd2l0aCBoZWFkKCkuCmBgYHtyfQpkdXBsaWNhdGVkLmh1Z28gPC0gbm9ybWFsaXplZF9jb3VudHNfYW5ub3RbZHVwbGljYXRlZChub3JtYWxpemVkX2NvdW50c19hbm5vdCRoZ25jX3N5bWJvbCksYygxLDIpXQpoZWFkKGR1cGxpY2F0ZWQuaHVnbykKYGBgCjxicj48YnI+ClNlZW1zIGxpa2UgbW9zdCBpZiBub3QgYWxsIGR1cGxpY2F0ZWQgSFVHTyBzeW1ib2xzIGFyZSBlaXRoZXIgZW1wdHkgc3RyaW5nIG9yIG1pc3NpbmcgdmFsdWVzIQo8YnI+PGJyPgpXaGF0IEkndmUgcmVhbGl6ZWQgdGhvdWdoIGlzIHRoYXQgd2hlbiB0aGVzZSB1bm1hcHBlZCBlbnNlbWJsIGdlbmUgaWRzIGFyZSBhbHNvIG1hcHBlZCB0bwoiZXh0ZXJuYWxfZ2VuZV9uYW1lIiBhdHRyaWJ1dGUsIHRoZXkgYWxsIGdvdCB0aG9zZSBuYW1lcyB0aGF0IHdlcmUgc2VhcmNoYWJsZSBvbiB0aGUgCmh0dHBzOi8vZ3JjaDM3LmVuc2VtYmwub3JnIHdlYnNpdGUuIEFuZCBmZXcgb2YgdGhlbSB3ZXJlIGV2ZW4gc2VhcmNoYWJsZSBvbiB0aGUgSFVHTwpodHRwczovL3d3dy5nZW5lbmFtZXMub3JnLyB3ZWJzaXRlLCB3aGlsZSBtb3N0IG9mIHRoZW0gd2VyZSBub3Qgc2VhcmNoYWJsZSBvbiBIVUdPIHdlYnNpdGUuCjxicj48YnI+ClVubWFwcGVkIEVuc2VtYmwgR2VuZSBJZHMgbWFwcGVkIHRvIEV4dGVybmFsIEdlbmUgTmFtZSBhdHRyaWJ1dGUKCmBgYHtyLCAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CmR1cGxpY2F0ZWQuaHVnby5tYXRyaXggPC0gZ2V0Qk0oYXR0cmlidXRlcyA9IGMoJ2Vuc2VtYmxfZ2VuZV9pZCcsICdleHRlcm5hbF9nZW5lX25hbWUnLCAiaGduY19zeW1ib2wiKSwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVycyA9ICJlbnNlbWJsX2dlbmVfaWQiLAogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBkdXBsaWNhdGVkLmh1Z28kZW5zZW1ibF9nZW5lX2lkLAogICAgICAgICAgICAgICAgICAgICAgICBtYXJ0ID0gZW5zZW1ibF9ncjM3KQoKaGVhZChkdXBsaWNhdGVkLmh1Z28ubWF0cml4KQoKYGBgCgo8YnI+PGJyPgpMZXQncyBjaGVjayBob3cgbWFueSBlbXB0eSBzdHJpbmdzIGFuZCBtaXNzaW5nIHZhbHVlcyBjb21wb3NlIHRoaXMgZW5zZW1ibCBnZW5lIGlkcyB3aXRob3V0CmhnbmMgc3ltYm9sIHRvIHNlZSBpZiB0aGVyZSBhcmUgYW55IGR1cGxpY2F0ZXMgdGhhdCBoYXZlIGhnbmMgc3ltYm9sIHJlcHJlc2VudGluZyBtb3JlIHRoYW4gMQplbnNlbWJsIGdlbmUgaWQuCjxicj48YnI+ClRoZSBudW1iZXIgb2YgZW1wdHkgc3RyaW5ncyBmb3IgZHVwbGljYXRlZCBoZ25jX3N5bWJvbApgYGB7cn0KCm51bWJlci5vZi5kdXBsaWNhdGlvbiA8LSBuY29sKGR1cGxpY2F0ZWQuaHVnby5tYXRyaXgpCgojIFRoZSBudW1iZXIgb2YgZW1wdHkgc3RyaW5ncyBmb3IgZHVwbGljYXRlZCBoZ25jX3N5bWJvbAoobnVtYmVyLm9mLmVtcHR5LnN0cmluZ3MuaW4uZHVwbGljYXRlZC5oZ25jLm1hdHJpeCA8LSBzdW0obmNoYXIoZHVwbGljYXRlZC5odWdvLm1hdHJpeCRoZ25jX3N5bWJvbCkgPT0gMCwgbmEucm0gPSBUUlVFKSkgCiAgICAKYGBgCjxicj48YnI+ClRoZSBudW1iZXIgb2YgbWlzc2luZyB2YWx1ZXMgZm9yIGR1cGxpY2F0ZWQgaGduY19zeW1ib2wKYGBge3J9CiMgVGhlIG51bWJlciBvZiBtaXNzaW5nIHZhbHVlcyBmb3IgZHVwbGljYXRlZCBoZ25jX3N5bWJvbAoobnVtYmVyLm9mLm1pc3NpbmcudmFsdWVzLmluLmR1cGxpY2F0ZWQuaGduYy5tYXRyaXggPC0gc3VtKGlzLm5hKGR1cGxpY2F0ZWQuaHVnby5tYXRyaXgkaGduY19zeW1ib2wpKSkgCiMKCmBgYAoKV2hlbiB0aGUgbnVtYmVyIG9mIG1pc3NpbmcgdmFsdWUgYW5kIHRoZSBudW1iZXIgb2YgZW10cHkgc3RyaW5ncyBhcmUgc3VtbWVkIGFuZCBjb21wYXJlZCBhZ2FpbnN0IHRoZQpudW1iZXIgb2YgZHVwbGljYXRlZCBIR05DIHN5bWJvbCwgdGhlIGxvZ2ljYWwgY29uZGl0aW9uYWwgb3V0cHV0cyBGQUxTRS4KYGBge3J9CiMgTGV0cyBjaGVjayB3aGV0aGVyIHRoZSB0d28gYWJvdmUgbnVtYmVycyBhZGQgdXAgdG8gdGhlIG51bWJlciBvZiBkdXBsaWNhdGVkIEhHTkMgc3ltYm9scwoKbnVtYmVyLm9mLmR1cGxpY2F0aW9uID09IG51bWJlci5vZi5lbXB0eS5zdHJpbmdzLmluLmR1cGxpY2F0ZWQuaGduYy5tYXRyaXggKyBudW1iZXIub2YubWlzc2luZy52YWx1ZXMuaW4uZHVwbGljYXRlZC5oZ25jLm1hdHJpeCAjIFsxXSBGQUxTRQpgYGAKVGhlcmUgaXMgMSBIR05DIHN5bWJvbCBkdXBsaWNhdGUgdGhhdCBpcyBuZWl0aGVyIGFuIGVtcHR5IHN0cmluZyBub3IgYSBtaXNzaW5nIHZhbHVlLgpgYGB7cn0Kc3VtKCEobmNoYXIoZHVwbGljYXRlZC5odWdvLm1hdHJpeCRoZ25jX3N5bWJvbCkgPT0gMCkgJiAhKGlzLm5hKGR1cGxpY2F0ZWQuaHVnby5tYXRyaXgkaGduY19zeW1ib2wpKSkgICAgCmBgYAoKCgpBbmQgaXQgaXMgdGhpcyEKYGBge3J9CnRoZS5pbmRleCA8LSB3aGljaCghKG5jaGFyKGR1cGxpY2F0ZWQuaHVnbyRoZ25jX3N5bWJvbCkgPT0gMCkgJiAhKGlzLm5hKGR1cGxpY2F0ZWQuaHVnbyRoZ25jX3N5bWJvbCkpKSAgICMgWzFdIDIxMTUKCmR1cGxpY2F0ZWQuaHVnby5tYXRyaXhbIHRoZS5pbmRleCwgXQojICAgICAgZW5zZW1ibF9nZW5lX2lkIGV4dGVybmFsX2dlbmVfbmFtZSBoZ25jX3N5bWJvbAojIDIxMTUgRU5TRzAwMDAwMjY2MDM2ICAgICAgICAgICAgTUlSMzYxNSAgICAgTUlSMzYxNQpgYGAKCkFuZCB0aGUgZGlmZmVyZW50IGVuc2VtYmwgSURzIHRoYXQgY29ycmVzcG9uZCB0byB0aGUgc3ltYm9sICJNSVIzNjE1IgpgYGB7cn0Kbm9ybWFsaXplZF9jb3VudHNfYW5ub3Rbd2hpY2gobm9ybWFsaXplZF9jb3VudHNfYW5ub3QkaGduY19zeW1ib2wgPT0gIk1JUjM2MTUiKSwgMTo2XQoKIyAgICAgICBlbnNlbWJsX2dlbmVfaWQgaGduY19zeW1ib2wgcHQuQS5QcmVUcmVhdCBwdC5BLkN5Y2xlMSBwdC5BLkN5Y2xlMyBwdC5BLkN5Y2xlNAojIDE2MzU2IEVOU0cwMDAwMDI2NDYyNCAgICAgTUlSMzYxNSAgICAgIDEuNTg1Mjg4ICAgIDEuNTg1Mjg4ICAgIDEuNTg1Mjg4ICAgIDEuNTg1Mjg4CiMgMTY0MTYgRU5TRzAwMDAwMjY2MDM2ICAgICBNSVIzNjE1ICAgICAgMS41ODUyODggICAgMS41ODUyODggICAgMS41ODUyODggICAgMi4yMDU1MDAKCmBgYApTZWFyY2hpbmcgdGhlIHR3byBlbnNlbWJsIGdlbmUgaWQgYXQgdGhlIGh0dHA6Ly9ncmNoMzcuZW5zZW1ibC5vcmcvIHRlbGxzIG1lIHRoYXQgb25lIGlzIGZvcndhcmQgc3RyYW5kIGFuZCB0aGUgYW5vdGhlciBpcyByZXZlcnNlIHN0cmFuZC4KPGJyPjxicj4KSSd2ZSBkZWNpZGVkIHRvIGtlZXAgYm90aCBvZiB0aGUgTUlSMzYxNCByb3dzIGJlY2F1c2UgdGhlIGV4cHJlc3Npb24gbGV2ZWwgd2FzIGRpZmZlcmVudCBiZXR3ZWVuIHRoZSBmb3J3YXJkIGFuZCByZXZlcnNlIHN0cmFuZCwgaW50ZXJlc3RpbmdseS4gQW5kIGJhc2VkIG9uIG15IHVuZGVyc3RhbmRpbmcgZnJvbSBtb2xlY3VsYXIgYmlvbG9neSBjbGFzc2VzLAp0aGUgUk5BIHBvbHltZXJhc2UgZG9lcyBub3Qga25vdyB3aGV0aGVyIHRoZSBnZW5lcyBzaG91bGQgYmUgdHJhbnNjcmliZWQgaW4gZWl0aGVyIG9uZSBvZiB0aGUgc3RyYW5kcyAoaS5lLiBpbiBlaXRoZXIgdHdvIGRpcmVjdGlvbnMpLCBhbHRob3VnaCBSTkEgcG9seW1lcmFzZSBkb2VzIHByZW1hdHVyZWx5IGhhbHQgd2hlbiBpdCBpcyBvbiB0aGUgbm9uLWNvZGluZyBzdHJhbmQuIAo8YnI+PGJyPgpOb3cgZm9yIHRoZSBwcm9ibGVtIG9mIHdoZXRoZXIgdG8ga2VlcCBvciBmaWx0ZXIgdGhlIG90aGVyIDI3MDggZXhwcmVzc2lvbiB2YWx1ZXMgdGhhdCBkbyBub3QgbWFwIHRvCkhHTkMgc3ltYm9sLCBJIHdhcyBpbnRyb2R1Y2VkIHRvIEhHTkNoZWxwZXIgcGFja2FnZSB0byBjaGVjayB3aGV0aGVyIHRoZSBleHRlcm5hbCBnZW5lIG5hbWVzIGhhdmUgCmJldHRlciB1cC10by1kYXRlIHJlY29tbWVuZGVkIG5hbWVzLgo8YnI+Cjxicj4KQW5kIG91dCBvZiB0aG9zZSBleHByZXNzaW9uIHZhbHVlcywgb25seSA4MiBvZiB0aGVtIGhhZCByZWNvbW1lbmRlZCBuYW1lcy4KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQpsaWJyYXJ5KEhHTkNoZWxwZXIpCmNoZWNrZWQuR2VuZS5TeW1ib2xzIDwtIGNoZWNrR2VuZVN5bWJvbHMoZHVwbGljYXRlZC5odWdvLm1hdHJpeCRleHRlcm5hbF9nZW5lX25hbWUpCgpoZWFkKGNoZWNrZWQuR2VuZS5TeW1ib2xzKQpzdW0oIWlzLm5hKGNoZWNrZWQuR2VuZS5TeW1ib2xzJFN1Z2dlc3RlZC5TeW1ib2wpKQoKYGBgCgpgYGB7ciwgV2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CiMgRmluYWwgRGF0YXNldAoKY29udmVyc2lvbl9zdGFzaCA8LSAiY2Q4X2lkX2NvbnZlcnNpb25fZmluYWwucmRzIgppZihmaWxlLmV4aXN0cyhjb252ZXJzaW9uX3N0YXNoKSl7CiAgY2Q4X2lkX2NvbnZlcnNpb25fZmluYWwgPC0gcmVhZFJEUyhjb252ZXJzaW9uX3N0YXNoKQp9IGVsc2UgewogIGNkOF9pZF9jb252ZXJzaW9uX2ZpbmFsIDwtIGdldEJNKGF0dHJpYnV0ZXMgPSBjKCJlbnNlbWJsX2dlbmVfaWQiLCJoZ25jX3N5bWJvbCIsICJleHRlcm5hbF9nZW5lX25hbWUiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcnMgPSBjKCJlbnNlbWJsX2dlbmVfaWQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGZhY3RvcihjZDhfZXhwX2ZpbHRlcmVkJGlkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcnQgPSBlbnNlbWJsX2dyMzcpCiAgc2F2ZVJEUyhjZDhfaWRfY29udmVyc2lvbl9maW5hbCwgY29udmVyc2lvbl9zdGFzaCkKfQoKbm9ybWFsaXplZF9jb3VudHNfYW5ub3RfZmluYWwgPC0gbWVyZ2UoeCA9IGNkOF9pZF9jb252ZXJzaW9uX2ZpbmFsLCB5ID0gbm9ybWFsaXplZF9jb3VudHMsYnkueCA9IDEsIGJ5LnkgPSAwLCBhbGwueT1UUlVFKQpjaGVja2VkLkdlbmUuU3ltYm9scyA8LSBjaGVja0dlbmVTeW1ib2xzKG5vcm1hbGl6ZWRfY291bnRzX2Fubm90X2ZpbmFsJGV4dGVybmFsX2dlbmVfbmFtZSkKbm9ybWFsaXplZF9jb3VudHNfYW5ub3RfZmluYWwgPC0gY2JpbmQobm9ybWFsaXplZF9jb3VudHNfYW5ub3RfZmluYWwsIGNoZWNrZWQuR2VuZS5TeW1ib2xzWyxjKDIsMyldKQpgYGAKPGJyPjxicj4KSSd2ZSBkZWNpZGVkIHRvIGtlZXAgYWxsIHRoZSAyNzA4IGV4cHJlc3Npb24gdmFsdWVzLCBhcyB0aGV5IGFyZSBhIHNpemFibGUgY2h1bmsgb2YgbXkgZGF0YSBhbmQgYXJlIHRob3NlIGdlbmVzIHRoYXQgbWF5IG5vdCBoYXZlIHRoZWlyIGZ1bmN0aW9ucyBhc3NpZ25lZCBidXQgYXJlIGV4cHJlc3NlZCB1cCB0byBjZXJ0YWluIGRlZ3JlZSBpbiBteSBzYW1wbGVzIHdpdGhvdXQgZ2V0dGluZyBkaXNjYXJkZWQgaW4gdGhlIGZpbHRlciBzdGVwLgo8YnI+PGJyPgpJJ3ZlIGRlY2lkZWQgdG8ga2VlcCBhbiBleHRyYSBjb2x1bW4gZm9yIGV4dGVybmFsX2dlbmVfbmFtZSBhdHRyaWJ1dGUgZm9yIGFsbCBteSBleHByZXNzaW9uIHZhbHVlIHJvd3MsIGFuZCBhbHNvIGluY2x1ZGUgdGhlIHJlY29tbWVuZGVkIG5hbWVzIGluIHRoZSBzdWdnZXN0ZWQuc3ltYm9sIGNvbHVtbiwgYmFzZWQgb24gZXh0ZXJuYWxfZ2VuZV9uYW1lIGNvbHVtbi4KPGJyPjxicj4KVW5mb3J0dW5hdGVseSwgdGhpcyBtZWFucyB0aGF0IHRoZSBmaW5hbCByZXN1bHQgb2YgbXkgZGF0YXNldCB3b3VsZCBoYXZlIG1hbnkgZ2VuZXMgdGhhdCBhcmUgbWlzc2luZyB0aGUgSFVHTyBnZW5lIHN5bWJvbC4gQW5kIG9uZSBvZiBteSBnZW5lcyBNSVIzNjE0IGhhcyBub24tdW5pcXVlIEhVR08gZ2VuZSBzeW1ib2wuCjxicj48YnI+CkhlcmUgaXMgYSBoZWFkIHZpZXcgb2YgbXkgZmluYWwgY3VyYXRlZCBkYXRhLgoKYGBge3J9CmhlYWQobm9ybWFsaXplZF9jb3VudHNfYW5ub3RfZmluYWwpCnNhdmVSRFMobm9ybWFsaXplZF9jb3VudHNfYW5ub3RfZmluYWwsIGZpbGUgPSAiUHJlcHJvY2Vzc2VkX0NEOF9BbnRpUEQxLlJEUyIpCmBgYAoKIyMKCiMjIEZpbmFsIENvdmVyYWdlIG9mIG15IERhdGFzZXQKClRoZSBEaW1lbnNpb24gb2YgbXkgRmluYWwgRGF0YSBGcmFtZSBvZiBOb3JtYWxpemVkIEV4cHJlc3Npb25zCmBgYHtyfQpkaW0obm9ybWFsaXplZF9jb3VudHNfYW5ub3RfZmluYWwpCgpgYGAKClRoZSBmaW5hbCBjb3ZlcmFnZSBvZiBteSBkYXRhc2V0IGhhcyAxNzEyMCBnZW5lcywgd2l0aCBqdXN0IG9uZSBkdXBsaWNhdGUgZ2VuZS4gQW5kIGl0IGhhcyA0IGRpZmZlcmVudCB0cmVhdG1lbnQgZ3JvdXBzLCB3aGVyZSBlYWNoIGdyb3VwIGhhdmUgMyBiaW9sb2dpY2FsIHJlcGxpY2F0ZXMuCjxicj48YnI+ClRoZXJlIGFyZSAyNzA4IGdlbmVzIHdpdGhvdXQgbWFwcGVkIEhVR08gZ2VuZSBzeW1ib2wsIGJ1dCBoYXZlIGV4dGVybmFsIG5hbWVzIHRoYXQgYWxsb3cgb25lIHRvIGlkZW50aWZ5IHRoZSBnZW5lLgoKCi0tLQpub2NpdGU6IHwKICBAaHVhbmcyMDE3dAouLi4KCiMjIyBSZWZlcmVuY2Vz